Patchwork [REPOST] Invalid Code when reading from unaligned zero-sized array

login
register
mail settings
Submitter Eric Botcazou
Date Dec. 6, 2013, 9 a.m.
Message ID <2249139.y74dSSf1GI@polaris>
Download mbox | patch
Permalink /patch/297639/
State New
Headers show

Comments

Eric Botcazou - Dec. 6, 2013, 9 a.m.
> 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.

Patch

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.  */