This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [REPOST] Invalid Code when reading from unaligned zero-sized array
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: Bernd Edlinger <bernd dot edlinger at hotmail dot de>
- Cc: gcc-patches at gcc dot gnu dot org, Jeff Law <law at redhat dot com>, Richard Biener <richard dot guenther at gmail dot com>, Jakub Jelinek <jakub at redhat dot com>
- Date: Fri, 06 Dec 2013 10:00:19 +0100
- Subject: Re: [REPOST] Invalid Code when reading from unaligned zero-sized array
- Authentication-results: sourceware.org; auth=none
- References: <DUB122-W20B5CD3C7B50824A33E21AE4D50 at phx dot gbl>
> one test case is this one:
>
> pr57748-3.c:
> /* PR middle-end/57748 */
> /* { dg-do run } */
> /* wrong code in expand_expr_real_1. */
>
> #include <stdlib.h>
>
> extern void abort (void);
>
> typedef long long V
> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>
> typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
>
> struct __attribute__((packed)) T { char c; P s; };
>
> void __attribute__((noinline, noclone))
> check (P *p)
> {
> if (p->b[0][0] != 3 || p->b[0][1] != 4)
> abort ();
> }
>
> void __attribute__((noinline, noclone))
> foo (struct T *t)
> {
> V a = { 3, 4 };
> t->s.b[0] = a;
> }
>
> int
> main ()
> {
> struct T *t = (struct T *) calloc (128, 1);
>
> foo (t);
> check (&t->s);
>
> free (t);
> return 0;
> }
>
>
> and the other one is
> pr57748-4.c:
> /* PR middle-end/57748 */
> /* { dg-do run } */
> /* wrong code in expand_expr_real_1. */
>
> #include <stdlib.h>
>
> extern void abort (void);
>
> typedef long long V
> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>
> typedef struct S { V b[1]; } P __attribute__((aligned (1)));
>
> struct __attribute__((packed)) T { char c; P s; };
>
> void __attribute__((noinline, noclone))
> check (P *p)
> {
> if (p->b[1][0] != 3 || p->b[1][1] != 4)
> abort ();
> }
>
> void __attribute__((noinline, noclone))
> foo (struct T *t)
> {
> V a = { 3, 4 };
> t->s.b[1] = a;
> }
>
> int
> main ()
> {
> struct T *t = (struct T *) calloc (128, 1);
>
> foo (t);
> check (&t->s);
>
> free (t);
> return 0;
> }
Here's the Correct Fix(tm). We may or may not decide to go for it because of
concerns about ABI changes; in the latter case, any kludge that we'll put in
place instead must be restricted to the cases caught by this patch.
* stor-layout.c (compute_record_mode): Return BLKmode for a trailing
array with size 0 or 1.
--
Eric Botcazou
Index: stor-layout.c
===================================================================
--- stor-layout.c (revision 205727)
+++ stor-layout.c (working copy)
@@ -1605,6 +1605,18 @@ compute_record_mode (tree type)
|| ! tree_fits_uhwi_p (DECL_SIZE (field)))
return;
+ /* As a GNU extension, we support out-of-bounds accesses for a trailing
+ array with size 0 or 1. In this case, the record type effectively
+ has variable size so it needs to have BLKmode. */
+ if (!DECL_CHAIN (field) && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
+ {
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (field));
+ if (!TYPE_MAX_VALUE (domain_type)
+ || integer_zerop (TYPE_MAX_VALUE (domain_type))
+ || integer_onep (TYPE_MAX_VALUE (domain_type)))
+ return;
+ }
+
/* If this field is the whole struct, remember its mode so
that, say, we can put a double in a class into a DF
register instead of forcing it to live in the stack. */