[Bug middle-end/93848] missing -Warray-bounds warning for array subscript 1 is outside array bounds

ch3root at openwall dot com gcc-bugzilla@gcc.gnu.org
Wed Feb 26 15:58:00 GMT 2020


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

--- Comment #9 from Alexander Cherepanov <ch3root at openwall dot com> ---
(In reply to Martin Sebor from comment #8)
> In
> 
>   int i[4];
>   int (*p)[4] = &i;
>   bar_aux (p[1]);
> 
> p[0] points to i and p[1] to (char*)&i + sizeof (i) (which is the same as
> &i[4]).

It seems we start to differ here. p[1] itself doesn't point anywhere. It's an
array, it has type int[4], its size is 4*sizeof(int). (That's easy to check.)
It's an lvalue that "potentially designates an object". Given that there is no
real object here, its evaluation is UB (C11, 6.3.2.1p1).

IOW there is no pointer here, UB happens before we get a pointer.

>  The latter is a pointer just past the end of i.  Evaluating
> past-the-end pointers is well-defined, as is all pointer arithmetic on them,
> just as long as the result is also a valid pointer to the same object (or
> just past its end).  The only way past-the-end pointers differ from others
> is that the former cannot be dereferenced (by any means, either the *
> operator, or [] or ->).

Right, but this is applicable to p+1, not to p[1]. Indeed, p+1 is a
past-the-end pointer, it points past the end of the array consisting of one
element (i). In particular, you can add 0 and -1 to it to roam over the array.
And you are right that you cannot apply * to it. That is, there is *(p+0) (it's
i) but there is no *(p+1). And p[1] is *(p+1) by definition, so evaluating it
is UB.

> In
>     int a[1][4];
>     printf("%p\n", (void *)&a[1][1]);
> 
> on the other hand, the reference to a[1][1] is undefined because a[1] is not
> a reference to an element in a but rather just past the end of a, and so it
> can be neither dereferenced nor used to obtain pointers other than to a or
> just past it.

Sorry I don't quite understand. Are you saying that a[1]-1 is valid? And the
result is a?

> &a[1] alone is valid (it's equivalent to (char*)&a + sizeof
> a) and points just past the end of a, but &a[1][1] is equivalent to
> (char*)&a + sizeof a + 1 which is not valid.

So we at least agree that &a[1][1] is UB and should give a warning and that
-Warray-bounds doesn't work as intended here?


More information about the Gcc-bugs mailing list