Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-10-05 Thread Szabolcs Nagy via Gcc-patches
The 09/23/2020 21:45, Jeff Law wrote:
> On 9/23/20 11:45 AM, Martin Sebor via Gcc-patches wrote:
> > On 9/23/20 9:44 AM, Szabolcs Nagy wrote:
> > > The 09/23/2020 09:22, Szabolcs Nagy wrote:
> > > > The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:
> > > > > On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:
> > > > > > After this patch, I am seeing this -Warray-parameter error:
> > > > > > 
> > > > > > In file included from ../include/pthread.h:1,
> > > > > >    from ../sysdeps/nptl/thread_db.h:25,
> > > > > >    from ../nptl/descr.h:32,
> > > > > >    from ../sysdeps/aarch64/nptl/tls.h:44,
> > > > > >    from ../include/errno.h:25,
> > > > > >    from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > > > > >    from :1:
> > > > > > ../sysdeps/nptl/pthread.h:734:47: error: argument 1 of
> > > > > > type ‘struct __jmp_buf_tag *’ declared as a pointer
> > > > > > [-Werror=array-parameter=]
> > > > > >     734 | extern int __sigsetjmp (struct __jmp_buf_tag
> > > > > > *__env, int __savemask) __THROWNL;
> > > > > >     | ~~^
> > > > > > In file included from ../include/setjmp.h:2,
> > > > > >    from ../nptl/descr.h:24,
> > > > > >    from ../sysdeps/aarch64/nptl/tls.h:44,
> > > > > >    from ../include/errno.h:25,
> > > > > >    from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > > > > >    from :1:
> > > > > > ../setjmp/setjmp.h:54:46: note: previously declared as
> > > > > > an array ‘struct __jmp_buf_tag[1]’
> > > > > >  54 | extern int __sigsetjmp (struct __jmp_buf_tag
> > > > > > __env[1], int __savemask) __THROWNL;
> > > > > >     | ~^~~~
> > > > > > cc1: all warnings being treated as errors
> > > > > 
> > > > > The warning flags differences between the forms of array parameters
> > > > > in redeclarations of the same function, including pointers vs arrays
> > > > > as in this instance.  It needs to be suppressed in glibc, either by
> > > > > making the function declarations consistent, or by #pragma diagnostic.
> > > > > (IIRC, the pointer declaration comes before struct __jmp_buf_tag has
> > > > > been defined so simply using the array form there doesn't work without
> > > > > defining the type first.)
> > > > > 
> > > > > I would expect the warning to be suppressed when using the installed
> > > > > library thanks to -Wno-system-headers.
> > > > 
> > > > why is this a warning? i'm not convinced it
> > > > should be in -Wall.
> > 
> > The main motivation for the warning is to detect unintentional
> > inconsistencies between function redeclarations that make deriving
> > true true intent difficult or impossible  (e.g, T[3] vs T[1], or
> > T[] vs T[1], or equivalently T* vs T[1]).
> > 
> > One goal is to support the convention where a constant array bound
> > in a function array parameter is used in lieu of the [static N]
> > notation (i.e., the minimum number of elements the caller is
> > expected to  make available).  The [static N] notation is little
> > known, used only exceedingly rarely, and isn't available in C++.
> > The array notation is used more often, although by no means common.
> > 
> > The ultimate goal is to motivate users to take advantage of GCC's
> > ability to check ordinary functions for out-of-bounds accesses to
> > array arguments.  The checking is only feasible if all declarations
> > of the same function, including its definition, use a consistent
> > notation to specify the same bound.  Including the strict
> > -Warray-parameter=2 setting in -Wall helps support this goal
> > (-Warray-parameter=1 doesn't warn for mismatches in the forms
> > of ordinary array bounds without [static].)
> > 
> > I mentioned the results of testing the patch with a number of
> > packages, including Glibc, Binutils/GDB, Glibc, and the kernel,
> > in the overview of the patch series:
> > https://gcc.gnu.org/pipermail/gcc-patches/2020-July/550920.html
> > It explains why I chose not to relax the warning to accommodate
> > the Glibc use case.
> > 
> > Based on my admittedly limited testing I'm not concerned about
> > the warning having adverse effects.  But if broader excposure
> > shows that it is prone to some it can certainly be adjusted.
> > Jeff does periodic mass rebuilds of all of Fedora with the top
> > of GCC trunk so we should know soon.
> 
> Yea.  If the patch was in last week's snapshot, then it should start
> spinning the 9000 Fedora packages later tonight alongside some Ranger 

Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-23 Thread Jeff Law via Gcc-patches



On 9/23/20 11:45 AM, Martin Sebor via Gcc-patches wrote:

On 9/23/20 9:44 AM, Szabolcs Nagy wrote:

The 09/23/2020 09:22, Szabolcs Nagy wrote:

The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:

On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:

After this patch, I am seeing this -Warray-parameter error:

In file included from ../include/pthread.h:1,
   from ../sysdeps/nptl/thread_db.h:25,
   from ../nptl/descr.h:32,
   from ../sysdeps/aarch64/nptl/tls.h:44,
   from ../include/errno.h:25,
   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
   from 
../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
   from 
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,

   from :1:
../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type 
‘struct __jmp_buf_tag *’ declared as a pointer 
[-Werror=array-parameter=]
    734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int 
__savemask) __THROWNL;

    | ~~^
In file included from ../include/setjmp.h:2,
   from ../nptl/descr.h:24,
   from ../sysdeps/aarch64/nptl/tls.h:44,
   from ../include/errno.h:25,
   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
   from 
../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
   from 
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,

   from :1:
../setjmp/setjmp.h:54:46: note: previously declared as an array 
‘struct __jmp_buf_tag[1]’
 54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], 
int __savemask) __THROWNL;

    | ~^~~~
cc1: all warnings being treated as errors


The warning flags differences between the forms of array parameters
in redeclarations of the same function, including pointers vs arrays
as in this instance.  It needs to be suppressed in glibc, either by
making the function declarations consistent, or by #pragma diagnostic.
(IIRC, the pointer declaration comes before struct __jmp_buf_tag has
been defined so simply using the array form there doesn't work without
defining the type first.)

I would expect the warning to be suppressed when using the installed
library thanks to -Wno-system-headers.


why is this a warning? i'm not convinced it
should be in -Wall.


The main motivation for the warning is to detect unintentional
inconsistencies between function redeclarations that make deriving
true true intent difficult or impossible  (e.g, T[3] vs T[1], or
T[] vs T[1], or equivalently T* vs T[1]).

One goal is to support the convention where a constant array bound
in a function array parameter is used in lieu of the [static N]
notation (i.e., the minimum number of elements the caller is
expected to  make available).  The [static N] notation is little
known, used only exceedingly rarely, and isn't available in C++.
The array notation is used more often, although by no means common.

The ultimate goal is to motivate users to take advantage of GCC's
ability to check ordinary functions for out-of-bounds accesses to
array arguments.  The checking is only feasible if all declarations
of the same function, including its definition, use a consistent
notation to specify the same bound.  Including the strict
-Warray-parameter=2 setting in -Wall helps support this goal
(-Warray-parameter=1 doesn't warn for mismatches in the forms
of ordinary array bounds without [static].)

I mentioned the results of testing the patch with a number of
packages, including Glibc, Binutils/GDB, Glibc, and the kernel,
in the overview of the patch series:
https://gcc.gnu.org/pipermail/gcc-patches/2020-July/550920.html
It explains why I chose not to relax the warning to accommodate
the Glibc use case.

Based on my admittedly limited testing I'm not concerned about
the warning having adverse effects.  But if broader excposure
shows that it is prone to some it can certainly be adjusted.
Jeff does periodic mass rebuilds of all of Fedora with the top
of GCC trunk so we should know soon.


Yea.  If the patch was in last week's snapshot, then it should start 
spinning the 9000 Fedora packages later tonight alongside some Ranger 
bits we're testing.  I'm on PTO till Monday though, so I won't be 
looking at the results until Tuesday probably...



jeff




Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-23 Thread Martin Sebor via Gcc-patches

On 9/23/20 9:44 AM, Szabolcs Nagy wrote:

The 09/23/2020 09:22, Szabolcs Nagy wrote:

The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:

On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:

After this patch, I am seeing this -Warray-parameter error:

In file included from ../include/pthread.h:1,
   from ../sysdeps/nptl/thread_db.h:25,
   from ../nptl/descr.h:32,
   from ../sysdeps/aarch64/nptl/tls.h:44,
   from ../include/errno.h:25,
   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
   from :1:
../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
__jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) 
__THROWNL;
| ~~^
In file included from ../include/setjmp.h:2,
   from ../nptl/descr.h:24,
   from ../sysdeps/aarch64/nptl/tls.h:44,
   from ../include/errno.h:25,
   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
   from :1:
../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
__jmp_buf_tag[1]’
 54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int 
__savemask) __THROWNL;
| ~^~~~
cc1: all warnings being treated as errors


The warning flags differences between the forms of array parameters
in redeclarations of the same function, including pointers vs arrays
as in this instance.  It needs to be suppressed in glibc, either by
making the function declarations consistent, or by #pragma diagnostic.
(IIRC, the pointer declaration comes before struct __jmp_buf_tag has
been defined so simply using the array form there doesn't work without
defining the type first.)

I would expect the warning to be suppressed when using the installed
library thanks to -Wno-system-headers.


why is this a warning? i'm not convinced it
should be in -Wall.


The main motivation for the warning is to detect unintentional
inconsistencies between function redeclarations that make deriving
true true intent difficult or impossible  (e.g, T[3] vs T[1], or
T[] vs T[1], or equivalently T* vs T[1]).

One goal is to support the convention where a constant array bound
in a function array parameter is used in lieu of the [static N]
notation (i.e., the minimum number of elements the caller is
expected to  make available).  The [static N] notation is little
known, used only exceedingly rarely, and isn't available in C++.
The array notation is used more often, although by no means common.

The ultimate goal is to motivate users to take advantage of GCC's
ability to check ordinary functions for out-of-bounds accesses to
array arguments.  The checking is only feasible if all declarations
of the same function, including its definition, use a consistent
notation to specify the same bound.  Including the strict
-Warray-parameter=2 setting in -Wall helps support this goal
(-Warray-parameter=1 doesn't warn for mismatches in the forms
of ordinary array bounds without [static].)

I mentioned the results of testing the patch with a number of
packages, including Glibc, Binutils/GDB, Glibc, and the kernel,
in the overview of the patch series:
https://gcc.gnu.org/pipermail/gcc-patches/2020-July/550920.html
It explains why I chose not to relax the warning to accommodate
the Glibc use case.

Based on my admittedly limited testing I'm not concerned about
the warning having adverse effects.  But if broader excposure
shows that it is prone to some it can certainly be adjusted.
Jeff does periodic mass rebuilds of all of Fedora with the top
of GCC trunk so we should know soon.

Martin



this is a warning with false positives that
have no portable workaround and does not
really help catching bugs (at least i doubt
inconsistent array vs pointer declaration
is causing common problems).

what gcc should warn about is if there is an
array style argument declaration and a caller
passes an array that's provably shorter than
that.


i take this back: such warning only makes
sense when the static keyword is used in
the array declarator.

i really think this issue should be fixed
in gcc and not in glibc: it's not true that
the argument has array type, the standard
requires the parameter type to be adjusted:

   A declaration of a parameter as "array of type"
   shall be adjusted to "qualified pointer to type"

this warning will just confuse users and
make them believe that the two declaration
styles for pointer arguments are somehow
different.





Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-23 Thread Szabolcs Nagy
The 09/23/2020 09:22, Szabolcs Nagy wrote:
> The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:
> > On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:
> > > After this patch, I am seeing this -Warray-parameter error:
> > > 
> > > In file included from ../include/pthread.h:1,
> > >   from ../sysdeps/nptl/thread_db.h:25,
> > >   from ../nptl/descr.h:32,
> > >   from ../sysdeps/aarch64/nptl/tls.h:44,
> > >   from ../include/errno.h:25,
> > >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > >   from :1:
> > > ../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
> > > __jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
> > >734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int 
> > > __savemask) __THROWNL;
> > >| ~~^
> > > In file included from ../include/setjmp.h:2,
> > >   from ../nptl/descr.h:24,
> > >   from ../sysdeps/aarch64/nptl/tls.h:44,
> > >   from ../include/errno.h:25,
> > >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > >   from :1:
> > > ../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
> > > __jmp_buf_tag[1]’
> > > 54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int 
> > > __savemask) __THROWNL;
> > >| ~^~~~
> > > cc1: all warnings being treated as errors
> > 
> > The warning flags differences between the forms of array parameters
> > in redeclarations of the same function, including pointers vs arrays
> > as in this instance.  It needs to be suppressed in glibc, either by
> > making the function declarations consistent, or by #pragma diagnostic.
> > (IIRC, the pointer declaration comes before struct __jmp_buf_tag has
> > been defined so simply using the array form there doesn't work without
> > defining the type first.)
> > 
> > I would expect the warning to be suppressed when using the installed
> > library thanks to -Wno-system-headers.
> 
> why is this a warning? i'm not convinced it
> should be in -Wall.
> 
> this is a warning with false positives that
> have no portable workaround and does not
> really help catching bugs (at least i doubt
> inconsistent array vs pointer declaration
> is causing common problems).
> 
> what gcc should warn about is if there is an
> array style argument declaration and a caller
> passes an array that's provably shorter than
> that.

i take this back: such warning only makes
sense when the static keyword is used in
the array declarator.

i really think this issue should be fixed
in gcc and not in glibc: it's not true that
the argument has array type, the standard
requires the parameter type to be adjusted:

  A declaration of a parameter as "array of type"
  shall be adjusted to "qualified pointer to type"

this warning will just confuse users and
make them believe that the two declaration
styles for pointer arguments are somehow
different.


Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-23 Thread Szabolcs Nagy
The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:
> On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:
> > After this patch, I am seeing this -Warray-parameter error:
> > 
> > In file included from ../include/pthread.h:1,
> >   from ../sysdeps/nptl/thread_db.h:25,
> >   from ../nptl/descr.h:32,
> >   from ../sysdeps/aarch64/nptl/tls.h:44,
> >   from ../include/errno.h:25,
> >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> >   from :1:
> > ../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
> > __jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
> >734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int 
> > __savemask) __THROWNL;
> >| ~~^
> > In file included from ../include/setjmp.h:2,
> >   from ../nptl/descr.h:24,
> >   from ../sysdeps/aarch64/nptl/tls.h:44,
> >   from ../include/errno.h:25,
> >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> >   from :1:
> > ../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
> > __jmp_buf_tag[1]’
> > 54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int 
> > __savemask) __THROWNL;
> >| ~^~~~
> > cc1: all warnings being treated as errors
> 
> The warning flags differences between the forms of array parameters
> in redeclarations of the same function, including pointers vs arrays
> as in this instance.  It needs to be suppressed in glibc, either by
> making the function declarations consistent, or by #pragma diagnostic.
> (IIRC, the pointer declaration comes before struct __jmp_buf_tag has
> been defined so simply using the array form there doesn't work without
> defining the type first.)
> 
> I would expect the warning to be suppressed when using the installed
> library thanks to -Wno-system-headers.

why is this a warning? i'm not convinced it
should be in -Wall.

this is a warning with false positives that
have no portable workaround and does not
really help catching bugs (at least i doubt
inconsistent array vs pointer declaration
is causing common problems).

what gcc should warn about is if there is an
array style argument declaration and a caller
passes an array that's provably shorter than
that.

pointer style declaration should be possible
to mix with array style (this is important
for standard headers but any api with multiple
implementations can end up in situations where
both array and pointer style decl will be
present).



Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-21 Thread Martin Sebor via Gcc-patches

On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:

After this patch, I am seeing this -Warray-parameter error:

In file included from ../include/pthread.h:1,
  from ../sysdeps/nptl/thread_db.h:25,
  from ../nptl/descr.h:32,
  from ../sysdeps/aarch64/nptl/tls.h:44,
  from ../include/errno.h:25,
  from ../sysdeps/unix/sysv/linux/sysdep.h:23,
  from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
  from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
  from :1:
../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
__jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
   734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) 
__THROWNL;
   | ~~^
In file included from ../include/setjmp.h:2,
  from ../nptl/descr.h:24,
  from ../sysdeps/aarch64/nptl/tls.h:44,
  from ../include/errno.h:25,
  from ../sysdeps/unix/sysv/linux/sysdep.h:23,
  from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
  from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
  from :1:
../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
__jmp_buf_tag[1]’
54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) 
__THROWNL;
   | ~^~~~
cc1: all warnings being treated as errors


The warning flags differences between the forms of array parameters
in redeclarations of the same function, including pointers vs arrays
as in this instance.  It needs to be suppressed in glibc, either by
making the function declarations consistent, or by #pragma diagnostic.
(IIRC, the pointer declaration comes before struct __jmp_buf_tag has
been defined so simply using the array form there doesn't work without
defining the type first.)

I would expect the warning to be suppressed when using the installed
library thanks to -Wno-system-headers.

Martin




The build/host/target setup is:
Build: x86_64-linux-gnu (Ubuntu 18.04)
Host: x86_64-linux-gnu
Target: aarch64-none-linux-gnu, aarch64_be-none-linux-gnu, 
arm-none-linux-gnueabi, arm-none-linux-gnueabihf



Kind regards
Vasee



On 20/09/2020, 01:02, "Gcc-patches on behalf of Martin Sebor via Gcc-patches" 
 wrote:

 On 9/17/20 4:38 PM, Joseph Myers wrote:
 > On Wed, 16 Sep 2020, Martin Sebor via Gcc-patches wrote:
 >
 >> Attached is an updated revision of the patch.  Besides the tweaks
 >> above it also contains a cosmetic change to the warning issued
 >> for mismatches in unspecified VLA bounds: it points at the decl
 >> with more of them to guide the user to specify them rather than
 >> make them all unspecified.
 >
 > The previous version of the patch had a while loop as previously 
discussed
 > to handle skipping multiple consecutive cdk_attrs.
 >
 > +  next = pd->declarator;
 > +  while (next && next->kind == cdk_attrs)
 > +   next = next->declarator;
 >
 > This version is back to an "if", but I don't see anything else in the new
 > version of that function that actually means the "if" would skip multiple
 > consecutive cdk_attrs as desired.
 >
 > The patch is OK with the "while" restored there.  If for some reason the
 > "while" breaks something, we'll need to look in more detail at exactly
 > what case isn't being handled correctly by "while".

 I guess it was the result of an experiment, trying to see if I could
 break it with the 'if'.  I (hope I) put it back and pushed the whole
 series.  I had to squash patches 1 and 2 because of a dependency that
 I had missed.

 Thanks for the review, by the way.  I think the signature validation
 we've ended up with is quite a bit more comprehensive than the first
 attempt.

 Martin





Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-21 Thread Vaseeharan Vinayagamoorthy
After this patch, I am seeing this -Warray-parameter error:

In file included from ../include/pthread.h:1,
 from ../sysdeps/nptl/thread_db.h:25,
 from ../nptl/descr.h:32,
 from ../sysdeps/aarch64/nptl/tls.h:44,
 from ../include/errno.h:25,
 from ../sysdeps/unix/sysv/linux/sysdep.h:23,
 from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
 from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
 from :1:
../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
__jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
  734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) 
__THROWNL;
  | ~~^
In file included from ../include/setjmp.h:2,
 from ../nptl/descr.h:24,
 from ../sysdeps/aarch64/nptl/tls.h:44,
 from ../include/errno.h:25,
 from ../sysdeps/unix/sysv/linux/sysdep.h:23,
 from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
 from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
 from :1:
../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
__jmp_buf_tag[1]’
   54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) 
__THROWNL;
  | ~^~~~
cc1: all warnings being treated as errors


The build/host/target setup is:
Build: x86_64-linux-gnu (Ubuntu 18.04)
Host: x86_64-linux-gnu
Target: aarch64-none-linux-gnu, aarch64_be-none-linux-gnu, 
arm-none-linux-gnueabi, arm-none-linux-gnueabihf



Kind regards
Vasee



On 20/09/2020, 01:02, "Gcc-patches on behalf of Martin Sebor via Gcc-patches" 
 wrote:

On 9/17/20 4:38 PM, Joseph Myers wrote:
> On Wed, 16 Sep 2020, Martin Sebor via Gcc-patches wrote:
> 
>> Attached is an updated revision of the patch.  Besides the tweaks
>> above it also contains a cosmetic change to the warning issued
>> for mismatches in unspecified VLA bounds: it points at the decl
>> with more of them to guide the user to specify them rather than
>> make them all unspecified.
> 
> The previous version of the patch had a while loop as previously discussed
> to handle skipping multiple consecutive cdk_attrs.
> 
> +  next = pd->declarator;
> +  while (next && next->kind == cdk_attrs)
> +   next = next->declarator;
> 
> This version is back to an "if", but I don't see anything else in the new
> version of that function that actually means the "if" would skip multiple
> consecutive cdk_attrs as desired.
> 
> The patch is OK with the "while" restored there.  If for some reason the
> "while" breaks something, we'll need to look in more detail at exactly
> what case isn't being handled correctly by "while".

I guess it was the result of an experiment, trying to see if I could
break it with the 'if'.  I (hope I) put it back and pushed the whole
series.  I had to squash patches 1 and 2 because of a dependency that
I had missed.

Thanks for the review, by the way.  I think the signature validation
we've ended up with is quite a bit more comprehensive than the first
attempt.

Martin



Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-19 Thread Martin Sebor via Gcc-patches

On 9/17/20 4:38 PM, Joseph Myers wrote:

On Wed, 16 Sep 2020, Martin Sebor via Gcc-patches wrote:


Attached is an updated revision of the patch.  Besides the tweaks
above it also contains a cosmetic change to the warning issued
for mismatches in unspecified VLA bounds: it points at the decl
with more of them to guide the user to specify them rather than
make them all unspecified.


The previous version of the patch had a while loop as previously discussed
to handle skipping multiple consecutive cdk_attrs.

+  next = pd->declarator;
+  while (next && next->kind == cdk_attrs)
+   next = next->declarator;

This version is back to an "if", but I don't see anything else in the new
version of that function that actually means the "if" would skip multiple
consecutive cdk_attrs as desired.

The patch is OK with the "while" restored there.  If for some reason the
"while" breaks something, we'll need to look in more detail at exactly
what case isn't being handled correctly by "while".


I guess it was the result of an experiment, trying to see if I could
break it with the 'if'.  I (hope I) put it back and pushed the whole
series.  I had to squash patches 1 and 2 because of a dependency that
I had missed.

Thanks for the review, by the way.  I think the signature validation
we've ended up with is quite a bit more comprehensive than the first
attempt.

Martin


Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-17 Thread Joseph Myers
On Wed, 16 Sep 2020, Martin Sebor via Gcc-patches wrote:

> Attached is an updated revision of the patch.  Besides the tweaks
> above it also contains a cosmetic change to the warning issued
> for mismatches in unspecified VLA bounds: it points at the decl
> with more of them to guide the user to specify them rather than
> make them all unspecified.

The previous version of the patch had a while loop as previously discussed 
to handle skipping multiple consecutive cdk_attrs.

+  next = pd->declarator;
+  while (next && next->kind == cdk_attrs)
+   next = next->declarator;

This version is back to an "if", but I don't see anything else in the new 
version of that function that actually means the "if" would skip multiple 
consecutive cdk_attrs as desired.

The patch is OK with the "while" restored there.  If for some reason the 
"while" breaks something, we'll need to look in more detail at exactly 
what case isn't being handled correctly by "while".

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-16 Thread Martin Sebor via Gcc-patches

On 9/15/20 5:02 PM, Joseph Myers wrote:

On Wed, 9 Sep 2020, Martin Sebor via Gcc-patches wrote:


Joseph, do you have any concerns with or comments on the most
recent patch or is it okay as is?

https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html


I'm not yet convinced by the logic for extracting an array bound from a
parameter declared using a typedef for an array type.

Say you have

typedef int A[3];

void f (A *x[*]);

so an argument that is an array, using [*], of pointers to arrays, where
those latter arrays are specified using the typedef.  As I read the logic,
first the pointer declarator is handled (ignored), then the array
declarator results in [*] being stored in spec, then the "if (pd->kind ==
cdk_id)" handling comes into play - and because spec is "*" and vbchain is
NULL_TREE, the upper bound of A gets extracted, but the upper bound of A
should be irrelevant here because it's a type that's the target of a
pointer.  The information from parm->specs->type logically comes before,
not after, the information from the declarator.


I see, you're right.  These arrays of pointers and pointers to arrays
are going to be the death of me...  Thanks for the test case.  I've
tweaked the function some more to handle it and added it to the test
suite.



As far as I can see, if one declaration gets part of the parameter type
(involving VLAs) from a typedef and another declaration gets that part of
the type directly in the declaration, the two spec strings constructed
might differ in the number of VLA bounds mentioned in the spec strings.
Is the code using those strings robust to handling the case where some of
the VLA bounds are missing because they came from a typedef?


Ugh.  I'd completely forgotten those are possible.  I've added code
to the function to handle those as well, and a new test to verify.
Hopefully I didn't open a can of worms by doing that.

Attached is an updated revision of the patch.  Besides the tweaks
above it also contains a cosmetic change to the warning issued
for mismatches in unspecified VLA bounds: it points at the decl
with more of them to guide the user to specify them rather than
make them all unspecified.

Martin
[2/5] - C front end support to detect out-of-bounds accesses to array parameters.

gcc/c-family/ChangeLog:

	PR c/50584
	* c-common.h (warn_parm_array_mismatch): Declare new function.
	(has_attribute): Move declaration of an existing function.
	(build_attr_access_from_parms): Declare new function.
	* c-warn.c (parm_array_as_string): Define new function.
	(plus_one):  Define new function.
	(warn_parm_ptrarray_mismatch): Define new function.
	(warn_parm_array_mismatch):  Define new function.
	(vla_bound_parm_decl): New function.
	* c.opt (-Warray-parameter, -Wvla-parameter): New options.
	* c-pretty-print.c (pp_c_type_qualifier_list): Don't print array type
	qualifiers here...
	(c_pretty_printer::direct_abstract_declarator): ...but instead print
	them in brackets here.  Also print [static].  Strip extraneous
	expressions from VLA bounds.

gcc/c/ChangeLog:

	PR c/50584
	* c-decl.c (lookup_last_decl): Define new function.
	(c_decl_attributes): Call it.
	(start_decl): Add argument and use it.
	(finish_decl): Call build_attr_access_from_parms and decl_attributes.
	(get_parm_array_spec): Define new function.
	(push_parm_decl): Call get_parm_array_spec.
	(start_function): Call warn_parm_array_mismatch.  Build attribute
	access and add it to current function.
	* c-parser.c (c_parser_declaration_or_fndef): Diagnose mismatches
	in forms of array parameters.
	* c-tree.h (start_decl): Add argument.

gcc/ChangeLog:

	PR c/50584
	* calls.c (initialize_argument_information): Remove assertion.
	* doc/invoke.texi (-Warray-parameter, -Wvla-parameter): Document.
	* tree-pretty-print.c (dump_generic_node): Correct handling of
	qualifiers.

gcc/testsuite/ChangeLog:

	PR c/50584
	* c-c++-common/Warray-bounds-6.c: Correct C++ declaration, adjust
	text of expected diagnostics.
	* gcc.dg/Wbuiltin-declaration-mismatch-9.c: Prune expected warning.
	* gcc.dg/Warray-parameter-2.c: New test.
	* gcc.dg/Warray-parameter-3.c: New test.
	* gcc.dg/Warray-parameter-4.c: New test.
	* gcc.dg/Warray-parameter-5.c: New test.
	* gcc.dg/Warray-parameter.c: New test.
	* gcc.dg/Wvla-parameter-2.c: New test.
	* gcc.dg/Wvla-parameter-3.c: New test.
	* gcc.dg/Wvla-parameter-4.c: New test.
	* gcc.dg/Wvla-parameter.c: New test.

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 4fc64bc4aa6..a61b25f95f1 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1321,6 +1321,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool);
 extern void warn_for_omitted_condop (location_t, tree);
 extern bool warn_for_restrict (unsigned, tree *, unsigned);
 extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
+extern void warn_parm_array_mismatch (location_t, tree, tree);
 
 /* Places where an lvalue, or modifiable lvalue, may be required.

Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-15 Thread Joseph Myers
On Wed, 9 Sep 2020, Martin Sebor via Gcc-patches wrote:

> Joseph, do you have any concerns with or comments on the most
> recent patch or is it okay as is?
> 
> https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

I'm not yet convinced by the logic for extracting an array bound from a 
parameter declared using a typedef for an array type.

Say you have

typedef int A[3];

void f (A *x[*]);

so an argument that is an array, using [*], of pointers to arrays, where 
those latter arrays are specified using the typedef.  As I read the logic, 
first the pointer declarator is handled (ignored), then the array 
declarator results in [*] being stored in spec, then the "if (pd->kind == 
cdk_id)" handling comes into play - and because spec is "*" and vbchain is 
NULL_TREE, the upper bound of A gets extracted, but the upper bound of A 
should be irrelevant here because it's a type that's the target of a 
pointer.  The information from parm->specs->type logically comes before, 
not after, the information from the declarator.

As far as I can see, if one declaration gets part of the parameter type 
(involving VLAs) from a typedef and another declaration gets that part of 
the type directly in the declaration, the two spec strings constructed 
might differ in the number of VLA bounds mentioned in the spec strings.  
Is the code using those strings robust to handling the case where some of 
the VLA bounds are missing because they came from a typedef?

-- 
Joseph S. Myers
jos...@codesourcery.com


[PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-09 Thread Martin Sebor via Gcc-patches

Joseph, do you have any concerns with or comments on the most
recent patch or is it okay as is?

https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

Martin

On 9/2/20 6:03 PM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

On 8/25/20 12:44 PM, Martin Sebor wrote:

Joseph, do you have any more comments on the rest of the most recent
revision of the patch?

https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

Martin

On 8/19/20 6:09 PM, Joseph Myers wrote:

On Wed, 19 Aug 2020, Martin Sebor via Gcc-patches wrote:

I think you need a while loop there, not just an if, to account for 
the
case of multiple consecutive cdk_attrs.  At least the GNU attribute 
syntax


 direct-declarator:
[...]
   ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of
parentheses with attributes inside.


I had considered a loop but couldn't find a way to trigger what you
describe (or a test in the testsuite that would do it) so I didn't
use one.  I saw loops like that in other places but I couldn't get
even those to uncover such a test case.  Here's what I tried:

   #define A(N) __attribute__ ((aligned (N), may_alias))
   int n;
   void f (int (* A (2) A (4) (* A (2) A (4) (* A (2) A (4) [n])[n])));

Sequences of consecutive attributes are all chained together.

I've added the loop here but I have no test for it.  It would be
good to add one if it really is needed.


The sort of thing I'm thinking of would be, where A is some attribute:

void f (int (A (A (A arg;

(that example doesn't involve an array, but it illustrates the syntax 
I'd

expect to produce multiple consecutive cdk_attrs).









[PING][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-02 Thread Martin Sebor via Gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

On 8/25/20 12:44 PM, Martin Sebor wrote:

Joseph, do you have any more comments on the rest of the most recent
revision of the patch?

https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

Martin

On 8/19/20 6:09 PM, Joseph Myers wrote:

On Wed, 19 Aug 2020, Martin Sebor via Gcc-patches wrote:


I think you need a while loop there, not just an if, to account for the
case of multiple consecutive cdk_attrs.  At least the GNU attribute 
syntax


 direct-declarator:
[...]
   ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of
parentheses with attributes inside.


I had considered a loop but couldn't find a way to trigger what you
describe (or a test in the testsuite that would do it) so I didn't
use one.  I saw loops like that in other places but I couldn't get
even those to uncover such a test case.  Here's what I tried:

   #define A(N) __attribute__ ((aligned (N), may_alias))
   int n;
   void f (int (* A (2) A (4) (* A (2) A (4) (* A (2) A (4) [n])[n])));

Sequences of consecutive attributes are all chained together.

I've added the loop here but I have no test for it.  It would be
good to add one if it really is needed.


The sort of thing I'm thinking of would be, where A is some attribute:

void f (int (A (A (A arg;

(that example doesn't involve an array, but it illustrates the syntax I'd
expect to produce multiple consecutive cdk_attrs).







Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-25 Thread Martin Sebor via Gcc-patches

Joseph, do you have any more comments on the rest of the most recent
revision of the patch?

https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552266.html

Martin

On 8/19/20 6:09 PM, Joseph Myers wrote:

On Wed, 19 Aug 2020, Martin Sebor via Gcc-patches wrote:


I think you need a while loop there, not just an if, to account for the
case of multiple consecutive cdk_attrs.  At least the GNU attribute syntax

 direct-declarator:
[...]
   ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of
parentheses with attributes inside.


I had considered a loop but couldn't find a way to trigger what you
describe (or a test in the testsuite that would do it) so I didn't
use one.  I saw loops like that in other places but I couldn't get
even those to uncover such a test case.  Here's what I tried:

   #define A(N) __attribute__ ((aligned (N), may_alias))
   int n;
   void f (int (* A (2) A (4) (* A (2) A (4) (* A (2) A (4) [n])[n])));

Sequences of consecutive attributes are all chained together.

I've added the loop here but I have no test for it.  It would be
good to add one if it really is needed.


The sort of thing I'm thinking of would be, where A is some attribute:

void f (int (A (A (A arg;

(that example doesn't involve an array, but it illustrates the syntax I'd
expect to produce multiple consecutive cdk_attrs).





Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-21 Thread Martin Sebor via Gcc-patches

On 8/19/20 6:09 PM, Joseph Myers wrote:

On Wed, 19 Aug 2020, Martin Sebor via Gcc-patches wrote:


I think you need a while loop there, not just an if, to account for the
case of multiple consecutive cdk_attrs.  At least the GNU attribute syntax

 direct-declarator:
[...]
   ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of
parentheses with attributes inside.


I had considered a loop but couldn't find a way to trigger what you
describe (or a test in the testsuite that would do it) so I didn't
use one.  I saw loops like that in other places but I couldn't get
even those to uncover such a test case.  Here's what I tried:

   #define A(N) __attribute__ ((aligned (N), may_alias))
   int n;
   void f (int (* A (2) A (4) (* A (2) A (4) (* A (2) A (4) [n])[n])));

Sequences of consecutive attributes are all chained together.

I've added the loop here but I have no test for it.  It would be
good to add one if it really is needed.


The sort of thing I'm thinking of would be, where A is some attribute:

void f (int (A (A (A arg;

(that example doesn't involve an array, but it illustrates the syntax I'd
expect to produce multiple consecutive cdk_attrs).


Yes, that does it, thanks.  But as a result of the test:

  if (pd->kind != cdk_array)
continue;

I don't see how to write a declaration where the if rather than
a loop would cause trouble.  If next->kind == cdk_attrs after
the test in the if statement (i.e., before I replaced it with
the while loop), the test above would be true and the for loop
would continue.  The next test for next->kind would then skip
over the attrs.

Let me know if I'm missing something.  Otherwise I'll just leave
the loop there with no test.

Martin


Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-19 Thread Joseph Myers
On Wed, 19 Aug 2020, Martin Sebor via Gcc-patches wrote:

> > I think you need a while loop there, not just an if, to account for the
> > case of multiple consecutive cdk_attrs.  At least the GNU attribute syntax
> > 
> > direct-declarator:
> > [...]
> >   ( gnu-attributes[opt] declarator )
> > 
> > should produce multiple consecutive cdk_attrs for each level of
> > parentheses with attributes inside.
> 
> I had considered a loop but couldn't find a way to trigger what you
> describe (or a test in the testsuite that would do it) so I didn't
> use one.  I saw loops like that in other places but I couldn't get
> even those to uncover such a test case.  Here's what I tried:
> 
>   #define A(N) __attribute__ ((aligned (N), may_alias))
>   int n;
>   void f (int (* A (2) A (4) (* A (2) A (4) (* A (2) A (4) [n])[n])));
> 
> Sequences of consecutive attributes are all chained together.
> 
> I've added the loop here but I have no test for it.  It would be
> good to add one if it really is needed.

The sort of thing I'm thinking of would be, where A is some attribute:

void f (int (A (A (A arg;

(that example doesn't involve an array, but it illustrates the syntax I'd 
expect to produce multiple consecutive cdk_attrs).

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-19 Thread Martin Sebor via Gcc-patches

On 8/17/20 4:09 PM, Joseph Myers wrote:

On Thu, 13 Aug 2020, Martin Sebor via Gcc-patches wrote:


* Maybe cdk_pointer is followed by cdk_attrs before cdk_id.  In this case
the code won't return.


I think I see the problem you're pointing out (I just don't see how
to trigger it or test that it doesn't happen).  If the tweak in
the attached update doesn't fix it a test case would be helpful.


I think you need a while loop there, not just an if, to account for the
case of multiple consecutive cdk_attrs.  At least the GNU attribute syntax

direct-declarator:
[...]
  ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of
parentheses with attributes inside.


I had considered a loop but couldn't find a way to trigger what you
describe (or a test in the testsuite that would do it) so I didn't
use one.  I saw loops like that in other places but I couldn't get
even those to uncover such a test case.  Here's what I tried:

  #define A(N) __attribute__ ((aligned (N), may_alias))
  int n;
  void f (int (* A (2) A (4) (* A (2) A (4) (* A (2) A (4) [n])[n])));

Sequences of consecutive attributes are all chained together.

I've added the loop here but I have no test for it.  It would be
good to add one if it really is needed.




* Maybe the code is correct to continue because we're in the case of an
array of pointers (cdk_array follows).  But as I understand it, the intent
is to set up an "arg spec" that describes only the (multidimensional)
array that is the parameter itself - not any array pointed to.  And it
looks to me like, in the case of an array of pointers to arrays, both sets
of array bounds would end up in the spec constructed.


Ideally, I'd like to check even pointers to arrays and so they should
be recorded somewhere.  The middle end code doesn't do any checking
of those yet for out-of-bounds accesses.  It wasn't a goal for
the first iteration so I've tweaked the code to avoid recording them.


Could you expand the comment on get_parm_array_spec to specify exactly
what you think the function should be putting in the returned attribute,
in what order, in cases where there are array declarators (constant,
empty, [*] and VLA) intermixed with other kinds of declarators and the
type from the type specifiers may or may not be an array type itself?
That will provide a basis for subsequent rounds of review of whether the
function is actually behaving as expected.


Done.



As far as I can see, the logic

+  if (TREE_CODE (nelts) == INTEGER_CST)
+   {
+ /* Skip all constant bounds except the most significant one.
+The interior ones are included in the array type.  */
+ if (next && (next->kind == cdk_array || next->kind == cdk_pointer))
+   continue;

will skip constant bounds in an array that's the target of a pointer
declarator, but not any other kind of bounds.  Is that what you intend -
that all the other kind of bounds in pointed-to arrays will be recorded in
this string?


The immediate goal (for the front end) is to detect differences
in the form ([] vs [N]) or value of the most significant bound
in parameters of array types (before they decay to pointers),
and differences in the form ([*] vs [n]) or (the presumed) value
(e.g., [n] vs [n + 1]) of VLA bounds.

So I need to encode every variable bound (specified or unspecified).
For ordinary arrays I want to encode just the form of the most
significant bound.




Then, the code

+  if (pd->kind == cdk_id)
+   {
+ /* Extract the upper bound from a parameter of an array type.  */

also seems misplaced.  If the type specifiers for the parameter are a
typedef for an array type, that array type should be processed *before*
the declarator to get the correct semantics (as if the bounds from those
type specifiers were given in the declarator), not at the end which gets
that type out of order with respect to array declarators.  (Processing
before the declarator also means clearing the results of that processing
if a pointer declarator is encountered at any point, because in that case
the array type in the type specifiers is irrelevant.)


I'm not sure I follow you here.  Can you show me what you mean on
a piece of code?  This test case (which IIUC does what you described)
works as expected:

$ cat q.c && gcc -O2 -S -Wall q.c
typedef int A[7][9];

void f (A[3][5]);


So this is equivalent to A[3][5][7][9].  The c_declarator structures have
the one for the [3] (the top-level bound) inside the one for the [5].
The [5] bound is skipped by the "Skip all constant bounds except the most
significant one." logic.  When the [3] bound is reached, the "break;" at
the end of that processing means the "Extract the upper bound from a
parameter of an array type." never gets executed.  Try replacing the [3]
bound by a VLA bound.  As I read the code, it will end up generating a
spec string that records first the VLA, then the [7], when it should be
first the 9 

Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-17 Thread Joseph Myers
On Thu, 13 Aug 2020, Martin Sebor via Gcc-patches wrote:

> > * Maybe cdk_pointer is followed by cdk_attrs before cdk_id.  In this case
> > the code won't return.
> 
> I think I see the problem you're pointing out (I just don't see how
> to trigger it or test that it doesn't happen).  If the tweak in
> the attached update doesn't fix it a test case would be helpful.

I think you need a while loop there, not just an if, to account for the 
case of multiple consecutive cdk_attrs.  At least the GNU attribute syntax

   direct-declarator:
[...]
 ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of 
parentheses with attributes inside.

> > * Maybe the code is correct to continue because we're in the case of an
> > array of pointers (cdk_array follows).  But as I understand it, the intent
> > is to set up an "arg spec" that describes only the (multidimensional)
> > array that is the parameter itself - not any array pointed to.  And it
> > looks to me like, in the case of an array of pointers to arrays, both sets
> > of array bounds would end up in the spec constructed.
> 
> Ideally, I'd like to check even pointers to arrays and so they should
> be recorded somewhere.  The middle end code doesn't do any checking
> of those yet for out-of-bounds accesses.  It wasn't a goal for
> the first iteration so I've tweaked the code to avoid recording them.

Could you expand the comment on get_parm_array_spec to specify exactly 
what you think the function should be putting in the returned attribute, 
in what order, in cases where there are array declarators (constant, 
empty, [*] and VLA) intermixed with other kinds of declarators and the 
type from the type specifiers may or may not be an array type itself?  
That will provide a basis for subsequent rounds of review of whether the 
function is actually behaving as expected.

As far as I can see, the logic

+  if (TREE_CODE (nelts) == INTEGER_CST)
+   {
+ /* Skip all constant bounds except the most significant one.
+The interior ones are included in the array type.  */
+ if (next && (next->kind == cdk_array || next->kind == cdk_pointer))
+   continue;

will skip constant bounds in an array that's the target of a pointer 
declarator, but not any other kind of bounds.  Is that what you intend - 
that all the other kind of bounds in pointed-to arrays will be recorded in 
this string?

> > Then, the code
> > 
> > +  if (pd->kind == cdk_id)
> > +   {
> > + /* Extract the upper bound from a parameter of an array type.  */
> > 
> > also seems misplaced.  If the type specifiers for the parameter are a
> > typedef for an array type, that array type should be processed *before*
> > the declarator to get the correct semantics (as if the bounds from those
> > type specifiers were given in the declarator), not at the end which gets
> > that type out of order with respect to array declarators.  (Processing
> > before the declarator also means clearing the results of that processing
> > if a pointer declarator is encountered at any point, because in that case
> > the array type in the type specifiers is irrelevant.)
> 
> I'm not sure I follow you here.  Can you show me what you mean on
> a piece of code?  This test case (which IIUC does what you described)
> works as expected:
> 
> $ cat q.c && gcc -O2 -S -Wall q.c
> typedef int A[7][9];
> 
> void f (A[3][5]);

So this is equivalent to A[3][5][7][9].  The c_declarator structures have 
the one for the [3] (the top-level bound) inside the one for the [5].  
The [5] bound is skipped by the "Skip all constant bounds except the most 
significant one." logic.  When the [3] bound is reached, the "break;" at 
the end of that processing means the "Extract the upper bound from a 
parameter of an array type." never gets executed.  Try replacing the [3] 
bound by a VLA bound.  As I read the code, it will end up generating a 
spec string that records first the VLA, then the [7], when it should be 
first the 9 (skipped), then the 7 (skipped), then the 5 (skipped), then 
the VLA.  Or if it's "void f (A *[variable][5]);", it will do the same 
thing (VLA, then 7, although both the 7 and the 9 are part of the 
pointed-to type).

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-13 Thread Martin Sebor via Gcc-patches

On 8/12/20 5:19 PM, Joseph Myers wrote:

On Fri, 7 Aug 2020, Martin Sebor via Gcc-patches wrote:


I don't see anything in the tests in this patch to cover this sort of case
(arrays of pointers, including arrays of pointers to arrays etc.).


I've added a few test cases and reworked the declarator parsing
(get_parm_array_spec) a bit, fixing some bugs.


I don't think get_parm_array_spec is yet logically right (and I don't see
tests of the sort of cases I'm concerned about, such as arrays of pointers
to arrays, or pointers with attributes applied to them).


Please have a look at the tests at the end of Warrary-parameter-4.c.
They should exercise the cases you brought up (as I understand them).
There are some tests for attributes in Warray-parameter.c.


You have logic

+  if (pd->kind == cdk_pointer
+ && (!next || next->kind == cdk_id))
+   {
+ /* Do nothing for the common case of a pointer.  The fact that
+the parameter is one can be deduced from the absence of
+an arg spec for it.  */
+ return attrs;
+   }

which is correct as far as it goes (when it returns with nothing done,
it's correct to do so, because the argument is indeed a pointer), but
incomplete:

* Maybe cdk_pointer is followed by cdk_attrs before cdk_id.  In this case
the code won't return.


I think I see the problem you're pointing out (I just don't see how
to trigger it or test that it doesn't happen).  If the tweak in
the attached update doesn't fix it a test case would be helpful.



* Maybe the code is correct to continue because we're in the case of an
array of pointers (cdk_array follows).  But as I understand it, the intent
is to set up an "arg spec" that describes only the (multidimensional)
array that is the parameter itself - not any array pointed to.  And it
looks to me like, in the case of an array of pointers to arrays, both sets
of array bounds would end up in the spec constructed.


Ideally, I'd like to check even pointers to arrays and so they should
be recorded somewhere.  The middle end code doesn't do any checking
of those yet for out-of-bounds accesses.  It wasn't a goal for
the first iteration so I've tweaked the code to avoid recording them.


What I think is correct is for both cdk_pointer and cdk_function to result
in the spec built up so far being cleared (regardless of what follows
cdk_pointer or cdk_function), rather than early return, so that the spec
present at the end is for the innermost sequence of array declarators
(possibly with attributes involved as well).  (cdk_function shouldn't
actually be an issue, since functions can't return arrays or functions,
but logically it seems appropriate to treat it like cdk_pointer.)


I've added a test for cdk_function to the one for cdk_pointer.



Then, the code

+  if (pd->kind == cdk_id)
+   {
+ /* Extract the upper bound from a parameter of an array type.  */

also seems misplaced.  If the type specifiers for the parameter are a
typedef for an array type, that array type should be processed *before*
the declarator to get the correct semantics (as if the bounds from those
type specifiers were given in the declarator), not at the end which gets
that type out of order with respect to array declarators.  (Processing
before the declarator also means clearing the results of that processing
if a pointer declarator is encountered at any point, because in that case
the array type in the type specifiers is irrelevant.)


I'm not sure I follow you here.  Can you show me what you mean on
a piece of code?  This test case (which IIUC does what you described)
works as expected:

$ cat q.c && gcc -O2 -S -Wall q.c
typedef int A[7][9];

void f (A[3][5]);
void f (A[1][5]);

void g (void)
{
  A a[2][5];
  f (a);
}
q.c:4:9: warning: argument 1 of type ‘int[1][5][7][9]’ with mismatched 
bound [-Warray-parameter=]

4 | void f (A[1][5]);
  | ^~~
q.c:3:9: note: previously declared as ‘int[3][5][7][9]’
3 | void f (A[3][5]);
  | ^~~
q.c: In function ‘g’:
q.c:9:3: warning: ‘f’ accessing 3780 bytes in a region of size 2520 
[-Wstringop-overflow=]

9 |   f (a);
  |   ^
q.c:9:3: note: referencing argument 1 of type ‘int (*)[5][7][9]’



The logic

+ /* Skip all constant bounds except the most significant one.
+The interior ones are included in the array type.  */
+ if (next && (next->kind == cdk_array || next->kind == cdk_pointer))
+   continue;

is another example of code that fails to look past cdk_attrs.


It should be handled by the tweak I added in the attached revision.

Martin

[2/5] - C front end support to detect out-of-bounds accesses to array parameters.

gcc/c-family/ChangeLog:

	PR c/50584
	* c-common.h (warn_parm_array_mismatch): Declare new function.
	(has_attribute): Move declaration of an existing function.
	(build_attr_access_from_parms): Declare new function.
	* c.opt (-Warray-parameter, -Wvla-parameter): New 

Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-12 Thread Joseph Myers
On Fri, 7 Aug 2020, Martin Sebor via Gcc-patches wrote:

> > I don't see anything in the tests in this patch to cover this sort of case
> > (arrays of pointers, including arrays of pointers to arrays etc.).
> 
> I've added a few test cases and reworked the declarator parsing
> (get_parm_array_spec) a bit, fixing some bugs.

I don't think get_parm_array_spec is yet logically right (and I don't see 
tests of the sort of cases I'm concerned about, such as arrays of pointers 
to arrays, or pointers with attributes applied to them).

You have logic

+  if (pd->kind == cdk_pointer
+ && (!next || next->kind == cdk_id))
+   {
+ /* Do nothing for the common case of a pointer.  The fact that
+the parameter is one can be deduced from the absence of
+an arg spec for it.  */
+ return attrs;
+   }

which is correct as far as it goes (when it returns with nothing done, 
it's correct to do so, because the argument is indeed a pointer), but 
incomplete:

* Maybe cdk_pointer is followed by cdk_attrs before cdk_id.  In this case 
the code won't return.

* Maybe the code is correct to continue because we're in the case of an 
array of pointers (cdk_array follows).  But as I understand it, the intent 
is to set up an "arg spec" that describes only the (multidimensional) 
array that is the parameter itself - not any array pointed to.  And it 
looks to me like, in the case of an array of pointers to arrays, both sets 
of array bounds would end up in the spec constructed.

What I think is correct is for both cdk_pointer and cdk_function to result 
in the spec built up so far being cleared (regardless of what follows 
cdk_pointer or cdk_function), rather than early return, so that the spec 
present at the end is for the innermost sequence of array declarators 
(possibly with attributes involved as well).  (cdk_function shouldn't 
actually be an issue, since functions can't return arrays or functions, 
but logically it seems appropriate to treat it like cdk_pointer.)

Then, the code

+  if (pd->kind == cdk_id)
+   {
+ /* Extract the upper bound from a parameter of an array type.  */

also seems misplaced.  If the type specifiers for the parameter are a 
typedef for an array type, that array type should be processed *before* 
the declarator to get the correct semantics (as if the bounds from those 
type specifiers were given in the declarator), not at the end which gets 
that type out of order with respect to array declarators.  (Processing 
before the declarator also means clearing the results of that processing 
if a pointer declarator is encountered at any point, because in that case 
the array type in the type specifiers is irrelevant.)

The logic

+ /* Skip all constant bounds except the most significant one.
+The interior ones are included in the array type.  */
+ if (next && (next->kind == cdk_array || next->kind == cdk_pointer))
+   continue;

is another example of code that fails to look past cdk_attrs.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-08-07 Thread Martin Sebor via Gcc-patches

On 7/29/20 12:12 PM, Joseph Myers wrote:

On Tue, 28 Jul 2020, Martin Sebor via Gcc-patches wrote:


+  /* A list of VLA variable bounds or null if not specified.  */
+  tree vbchain = NULL_TREE;
+  if (parm->declarator->kind == cdk_array)



+ if (pd->kind != cdk_array)
+   break;



+ /* Skip all constant bounds except the most significant
+one.  The interior ones are included in the array type.  */
+ if (next && next->kind == cdk_array)
+   continue;


Anything working with declarators should typically have logic to skip
cdk_attrs declarators.


Thanks for the quick review/reply and the hints below!


For example, a parameter is declared as an array using [] in that
declarator if the innermost c_declarator that is not cdk_id or cdk_attrs
is of kind cdk_array.  (It's the innermost not the outermost because of C
declarator syntax.)  The array bounds for the parameter array itself (as
opposed to any other bounds if the parameter is e.g. an array of pointers
to arrays) are then those in all the cdk_array declarators after the last
declarator (if any) that's not cdk_array, cdk_attrs or cdk_id (cdk_id only
comes in the last place).

If e.g. the parameter has the nested cdk_declarator sequence

cdk_function
cdk_pointer
cdk_array
cdk_attrs
cdk_array
cdk_pointer
cdk_array
cdk_attrs
cdk_array
cdk_array
cdk_id

then it's a three-dimensional array of pointers to two-dimensional arrays
of pointers to functions.

I don't see anything in the tests in this patch to cover this sort of case
(arrays of pointers, including arrays of pointers to arrays etc.).


I've added a few test cases and reworked the declarator parsing
(get_parm_array_spec) a bit, fixing some bugs.

While testing I also noticed a problem/limitation in the array/VLA
formatting function that I couldn't think of how to fix without
duplicating a lot of what the C/C++ pretty printer does.  So
the updated patch also includes changes to the pretty printer to
do most of what I need.  As may be evident from the comments, I'm
not very happy with the solution but my only other idea was to add
a bit to an array type to indicate whether it's [static N] or [*]
and that seems too intrusive.  If you find the "hack" I put in
unacceptable for the initial patch I'd appreciate a suggestion
for a cleaner approach.  I'd like to  fix that in a followup
patch.

The pretty printer formatting only produces [*] for the most
significant unspecified VLA bound, and the whole machinery
ignores [static] on VLA bounds.  I'd like to fix both but I
thought I'd get your suggestion for how to make [*] appear
in inner bounds first.

Martin
[2/5] - C front end support to detect out-of-bounds accesses to array parameters.

gcc/c-family/ChangeLog:

	PR c/50584
	* c-common.h (warn_parm_array_mismatch): Declare new function.
	(has_attribute): Move declaration of an existing function.
	(build_attr_access_from_parms): Declare new function.
	* c.opt (-Warray-parameter, -Wvla-parameter): New options.
	* c-pretty-print.c (pp_c_type_qualifier_list): Don't print array type
	qualifiers here...
	(c_pretty_printer::direct_abstract_declarator): ...but instead print
	them in brackets here.  Also print [static].  Strip extraneous
	expressions from VLA bounds.

gcc/c/ChangeLog:

	PR c/50584
	* c-decl.c (lookup_last_decl): Define new function.
	(c_decl_attributes): Call it.
	(start_decl): Add argument and use it.
	(finish_decl): Call build_attr_access_from_parms and decl_attributes.
	(get_parm_array_spec): Define new function.
	(push_parm_decl): Call get_parm_array_spec.
	(start_function): Call warn_parm_array_mismatch.  Build attribute
	access and add it to current function.
	* c-parser.c (c_parser_declaration_or_fndef): Diagnose mismatches
	in forms of array parameters.
	* c-tree.h (start_decl): Add argument.

gcc/ChangeLog:

	PR c/50584
	* calls.c (initialize_argument_information): Remove assertion.
	* doc/invoke.texi (-Warray-parameter, -Wvla-parameter): Document.
	* tree-pretty-print.c (dump_generic_node): Correct handling of
	qualifiers.

gcc/testsuite/ChangeLog:

	PR c/50584
	* c-c++-common/Warray-bounds-6.c: Correct C++ declaration, adjust
	text of expected diagnostics.
	* gcc.dg/Wbuiltin-declaration-mismatch-9.c: Prune expected warning.
	* gcc.dg/Warray-parameter-2.c: New test.
	* gcc.dg/Warray-parameter-3.c: New test.
	* gcc.dg/Warray-parameter-4.c: New test.
	* gcc.dg/Warray-parameter.c: New test.
	* gcc.dg/Wvla-parameter-2.c: New test.
	* gcc.dg/Wvla-parameter.c: New test.

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 61627264e1e..8070ae7f0d1 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1319,6 +1319,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool);
 extern void warn_for_omitted_condop (location_t, tree);
 extern bool warn_for_restrict (unsigned, tree *, unsigned);
 extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
+extern void 

Re: [PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-07-29 Thread Joseph Myers
On Tue, 28 Jul 2020, Martin Sebor via Gcc-patches wrote:

> +  /* A list of VLA variable bounds or null if not specified.  */
> +  tree vbchain = NULL_TREE;
> +  if (parm->declarator->kind == cdk_array)

> +   if (pd->kind != cdk_array)
> + break;

> +   /* Skip all constant bounds except the most significant
> +  one.  The interior ones are included in the array type.  */
> +   if (next && next->kind == cdk_array)
> + continue;

Anything working with declarators should typically have logic to skip 
cdk_attrs declarators.

For example, a parameter is declared as an array using [] in that 
declarator if the innermost c_declarator that is not cdk_id or cdk_attrs 
is of kind cdk_array.  (It's the innermost not the outermost because of C 
declarator syntax.)  The array bounds for the parameter array itself (as 
opposed to any other bounds if the parameter is e.g. an array of pointers 
to arrays) are then those in all the cdk_array declarators after the last 
declarator (if any) that's not cdk_array, cdk_attrs or cdk_id (cdk_id only 
comes in the last place).

If e.g. the parameter has the nested cdk_declarator sequence

cdk_function
cdk_pointer
cdk_array
cdk_attrs
cdk_array
cdk_pointer
cdk_array
cdk_attrs
cdk_array
cdk_array
cdk_id

then it's a three-dimensional array of pointers to two-dimensional arrays 
of pointers to functions.

I don't see anything in the tests in this patch to cover this sort of case 
(arrays of pointers, including arrays of pointers to arrays etc.).

-- 
Joseph S. Myers
jos...@codesourcery.com


[PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-07-28 Thread Martin Sebor via Gcc-patches

Patch 2 adds support for the internal attribute access specification
for array/VLA parameters to the C front end and two new options to
control warnings.

The attribute is added in two steps: first, push_parm_decl adds a new
attribute "arg spec" to each array parameter with a string describing
its form and a chain of VLA bounds, and next start_function, after
checking for mismatches with prior declarations, collects these for
each function definitionm, creates an attribute access specification
from them, and installs it in the declaration.
c_parser_declaration_or_fndef does the same for function declarations
that aren't definitions.  The two-step process via attribute "arg spec"
is necessary to associate VLA bounds with VLA parameters, and because
function parameters are transient (they're not available in the middle
end).
[2/5] - C front end support to detect out-of-bounds accesses to array parameters.

gcc/c-family/ChangeLog:

	PR c/50584
	* c-common.h (warn_parm_array_mismatch): Declare new function.
	(has_attribute): Move declaration of an existing function.
	(build_attr_access_from_parms): Declare new function.
	* c.opt (-Warray-parameter, -Wvla-parameter): New options.

gcc/c/ChangeLog:

	PR c/50584
	* c-decl.c (lookup_last_decl): Define new function.
	(c_decl_attributes): Call it.
	(start_decl): Add argument and use it.
	(finish_decl): Call build_attr_access_from_parms and decl_attributes.
	(get_parm_array_spec): Define new function.
	(push_parm_decl): Call get_parm_array_spec.
	(start_function): Call warn_parm_array_mismatch.  Build attribute
	access and add it to current function.
	* c-parser.c (c_parser_declaration_or_fndef): Diagnose mismatches
	in forms of array parameters.
	* c-tree.h (start_decl): Add argument.

gcc/ChangeLog:

	PR c/50584
	* calls.c (initialize_argument_information): Remove assertion.
	* doc/invoke.texi (-Warray-parameter, -Wvla-parameter): Document.
	* tree-pretty-print.c (dump_generic_node): Correct handling of
	qualifiers.

gcc/testsuite/ChangeLog:

	PR c/50584
	* c-c++-common/Warray-bounds-6.c: Correct C++ declaration, adjust
	text of expected diagnostics.
	* gcc.dg/Wbuiltin-declaration-mismatch-9.c: Prune expected warning.
	* gcc.dg/Warray-parameter-2.c: New test.
	* gcc.dg/Warray-parameter-3.c: New test.
	* gcc.dg/Warray-parameter-4.c: New test.
	* gcc.dg/Warray-parameter.c: New test.
	* gcc.dg/Wvla-parameter-2.c: New test.
	* gcc.dg/Wvla-parameter.c: New test.

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 61627264e1e..8070ae7f0d1 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1319,6 +1319,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool);
 extern void warn_for_omitted_condop (location_t, tree);
 extern bool warn_for_restrict (unsigned, tree *, unsigned);
 extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
+extern void warn_parm_array_mismatch (location_t, tree, tree);
 
 /* Places where an lvalue, or modifiable lvalue, may be required.
Used to select diagnostic messages in lvalue_error and
@@ -1373,6 +1374,8 @@ extern tree find_tm_attribute (tree);
 extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[];
 extern const struct attribute_spec::exclusions attr_noreturn_exclusions[];
 extern tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+extern bool has_attribute (location_t, tree, tree, tree (*)(tree));
+extern tree build_attr_access_from_parms (tree, bool);
 
 /* In c-format.c.  */
 extern bool valid_format_string_type_p (tree);
@@ -1401,8 +1404,6 @@ extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 		   location_t prev_token_loc);
 extern tree braced_lists_to_strings (tree, tree);
 
-extern bool has_attribute (location_t, tree, tree, tree (*)(tree));
-
 #if CHECKING_P
 namespace selftest {
   /* Declarations for specific families of tests within c-family,
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 2b1aca16eb4..6f3997405a1 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -338,6 +338,14 @@ Warray-bounds=
 LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0)
 ; in common.opt
 
+Warray-parameter
+C ObjC C++ ObjC++ Warning Alias(Warray-parameter=, 2, 0)
+Warn about mismatched declarations of array parameters and unsafe accesses to them.
+
+Warray-parameter=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_array_parameter) IntegerRange(0, 2) LangEnabledBy(C ObjC C++ ObjC++,Wall, 2, 0) Warning
+Warn about mismatched declarations of array parameters and unsafe accesses to them.
+
 Wzero-length-bounds
 C ObjC C++ ObjC++ Var(warn_zero_length_bounds) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
 Warn about accesses to interior zero-length array members.
@@ -1253,6 +1261,10 @@ Wno-vla-larger-than
 C ObjC C++ LTO ObjC++ Alias(Wvla-larger-than=,18446744073709551615EiB,none) Warning
 Disable Wvla-larger-than= warning.  Equivalent to Wvla-larger-than= or larger.
 
+Wvla-parameter
+C