This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] enhance -Warray-bounds to handle strings and excessive indices


On 10/19/2017 02:34 AM, Richard Biener wrote:
On Thu, Oct 19, 2017 at 1:19 AM, Martin Sebor <msebor@gmail.com> wrote:
On 10/18/2017 04:48 AM, Richard Biener wrote:

On Wed, Oct 18, 2017 at 5:34 AM, Martin Sebor <msebor@gmail.com> wrote:

While testing my latest -Wrestrict changes I noticed a number of
opportunities to improve the -Warray-bounds warning.  Attached
is a patch that implements a solution for the following subset
of these:

PR tree-optimization/82596 - missing -Warray-bounds on an out-of
  bounds index into string literal
PR tree-optimization/82588 - missing -Warray-bounds on an excessively
  large index
PR tree-optimization/82583 - missing -Warray-bounds on out-of-bounds
  inner indices

I meant to use size_type_node (size_t), not sizetype.  But
I just checked that ptrdiff_type_node is initialized in
build_common_tree_nodes and thus always available.

I see.  Using ptrdiff_type_node is preferable for the targets
where ptrdiff_t has a greater precision than size_t (e.g., VMS).
It makes sense now.  I should remember to change all the other
places where I introduced ssizetype to use ptrdiff_type_node.


As an aside, at some point I would like to get away from a type
based limit in all these warnings and instead use one that can
be controlled by an option so that a user can impose a lower limit
on the maximum size of an object and have all size-related warnings
(and perhaps even optimizations) enforce it and benefit from it.

You could add a --param that is initialized from ptrdiff_type_node.

Yes, that's an option to consider.  Thanks.


+      tree arg = TREE_OPERAND (ref, 0);
+      tree_code code = TREE_CODE (arg);
+      if (code == COMPONENT_REF)
+       {
+         HOST_WIDE_INT off;
+         if (tree base = get_addr_base_and_unit_offset (ref, &off))
+           up_bound_p1 = fold_build2 (MINUS_EXPR, ssizetype, up_bound_p1,
+                                      TYPE_SIZE_UNIT (TREE_TYPE (base)));
+         else
+           return;

so this gives up on a.b[i].c.d[k] (ok, array_at_struct_end_p will be
false).
simply not subtracting anyhing instead of returning would be
conservatively
correct, no?  Likewise subtracting the offset of the array for all
"previous"
variably indexed components with assuming the lowest value for the index.
But as above I think compensating for the offset of the array within the
object
is academic ... ;)


I was going to say yes (it gives up) but on second thought I don't
think it does.  Only the major index can be unbounded and the code
does consider the size of the sub-array when checking the major
index.  So, IIUC, I think this works correctly as is (*).  What
doesn't work is VLAs but those are a separate problem.  Let me
know if I misunderstood your question.

get_addr_base_and_unit_offset will return NULL if there's any variable
component in 'ref'.  So as written it seems to be dead code (you
want to pass 'arg'?)

Sorry, I'm not sure I understand what you mean.  What do you think
is dead code?  The call to get_addr_base_and_unit_offset() is also
made for an array of unspecified bound (up_bound is null) and for
an array at the end of a struct.  For those the function returns
non-null, and for the others (arrays of runtime bound) it returns
null.  (I passed arg instead of ref but I see no difference in
my tests.)


I was asking you to remove the 'else return' because w/o subtracting
the upper bound is just more conservative.

Sure, that sounds good.

Attached is an updated patch.

Thanks
Martin
PR tree-optimization/82588 - missing -Warray-bounds on a excessively large index
PR tree-optimization/82583 - missing -Warray-bounds on out-of-bounds inner indic

gcc/ChangeLog:
	PR tree-optimization/82588
	PR tree-optimization/82583
	* tree-vrp.c (check_array_ref): Handle flexible array members,
	string literals, and inner indices.
	(search_for_addr_array): Add detail to diagnostics.

gcc/testsuite/ChangeLog:
	PR tree-optimization/82588
	PR tree-optimization/82583	
	* c-c++-common/Warray-bounds.c: New test.
	* gcc.dg/Warray-bounds-11.c: Adjust.
	* gcc.dg/Warray-bounds-22.c: New test.

diff --git a/gcc/testsuite/c-c++-common/Warray-bounds.c b/gcc/testsuite/c-c++-common/Warray-bounds.c
new file mode 100644
index 0000000..2207999
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-bounds.c
@@ -0,0 +1,240 @@
+/* PR tree-optimization/82588 - missing -Warray-bounds on an excessively
+   large index
+   { dg-do compile }
+   { dg-options "-O2 -Warray-bounds -ftrack-macro-expansion=0" }  */
+
+#define SIZE_MAX  __SIZE_MAX__
+#define SSIZE_MAX __PTRDIFF_MAX__
+#define SSIZE_MIN (-SSIZE_MAX - 1)
+
+typedef __PTRDIFF_TYPE__ ssize_t;
+typedef __SIZE_TYPE__    size_t;
+
+extern ssize_t signed_value (void)
+{
+  extern volatile ssize_t signed_value_source;
+  return signed_value_source;
+}
+
+extern size_t unsigned_value (void)
+{
+  extern volatile size_t unsigned_value_source;
+  return unsigned_value_source;
+}
+
+ssize_t signed_range (ssize_t min, ssize_t max)
+{
+  ssize_t val = signed_value ();
+  return val < min || max < val ? min : val;
+}
+
+struct AX { int n; char ax[]; };
+
+struct A1 { int i; char a1[1]; };
+struct B { int i; struct A1 a1x[]; };
+
+void sink (int, ...);
+
+#define R(min, max) signed_range (min, max)
+#define T(expr)     sink (0, expr)
+
+struct __attribute__ ((packed)) S16 { unsigned i: 16; };
+
+void farr_char (void)
+{
+  extern char ac[];
+
+  T (ac[SSIZE_MIN]);                      /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .char *\\\[]." } */
+  T (ac[-1]);                             /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (ac[0]);
+
+  T (ac[SSIZE_MAX - 1]);
+  T (ac[SSIZE_MAX]);                      /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (ac[SSIZE_MAX + (size_t)1]);          /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (ac[SIZE_MAX]);                       /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+}
+
+void farr_s16 (void)
+{
+  extern struct S16 ax[];
+
+  T (ax[SSIZE_MIN]);                      /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(struct )?S16 *\\\[]." } */
+  T (ax[-1]);                             /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (ax[0]);
+
+  T (ax[SSIZE_MAX / 2 - 1]);
+  T (ax[SSIZE_MAX / 2]);                  /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (ax[SSIZE_MAX / 2 + (size_t)1]);      /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (ax[SIZE_MAX]);                       /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+}
+
+void farr_s16_7 (void)
+{
+  extern struct S16 ax_7[][7];
+
+  T (ax_7[0][SSIZE_MIN]);                 /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(struct )?S16 *\\\[7]." } */
+  T (ax_7[0][-1]);                        /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (ax_7[0][0]);
+  T (ax_7[0][7]);                        /* { dg-warning "array subscript 7 is above array bounds of .(struct )?S16 *\\\[7]." } */
+  T (ax_7[0][8]);                        /* { dg-warning "array subscript 8 is above array bounds of .(struct )?S16 *\\\[7]." } */
+
+  T (ax_7[0][SSIZE_MAX / 2]);            /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (ax_7[0][SIZE_MAX]);                 /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (ax_7[SSIZE_MIN][0]);                 /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(struct )?S16 *\\\[]\\\[7]." } */
+  T (ax_7[-1][0]);                        /* { dg-warning "array subscript -1 is below array bounds" } */
+
+  T (ax_7[SSIZE_MAX / 2][0]);             /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (ax_7[SIZE_MAX][0]);                  /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  ssize_t i = R (SSIZE_MIN, -1);
+  T (ax_7[i][0]);                         /* { dg-warning "array subscript -1 is below array bounds" } */
+
+  T (ax_7[R (SSIZE_MIN, 0)][0]);
+  T (ax_7[R (-1, 0)][0]);
+  T (ax_7[R (-1, 1)][0]);
+  T (ax_7[R (-1, 7)][0]);
+  T (ax_7[R (-1, SSIZE_MAX)][0]);
+
+  T (ax_7[R ( 1, SSIZE_MAX)][0]);
+  T (ax_7[R (SSIZE_MAX / 14 - 1, SSIZE_MAX)][0]);
+
+  i = R (SSIZE_MAX / 14, SSIZE_MAX);
+  T (ax_7[i][0]);                         /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (ax_7[0][R (SSIZE_MIN, 0)]);
+  T (ax_7[0][R (-1, 0)]);
+  T (ax_7[0][R (-1, 1)]);
+  T (ax_7[0][R (-1, 7)]);
+  T (ax_7[0][R (-1, SSIZE_MAX)]);
+  T (ax_7[0][R (-1, SSIZE_MAX)]);
+
+  T (ax_7[0][R (1, SSIZE_MAX)]);
+  T (ax_7[0][R (7, SSIZE_MAX)]);          /* { dg-warning "array subscript 7 is above array bounds" } */
+
+}
+
+void farr_x_5_7 (void)
+{
+  extern struct S16 a[][5][7];
+
+  T (a[0][0][-3]);                        /* { dg-warning "array subscript -3 is below array bounds of .(struct )?S16 *\\\[7]." } */
+  T (a[0][-2][0]);                        /* { dg-warning "array subscript -2 is below array bounds of .(struct )?S16 *\\\[5]\\\[7]." } */
+  T (a[-1][0][0]);                        /* { dg-warning "array subscript -1 is below array bounds of .(struct )?S16 *\\\[]\\\[5]\\\[7]." } */
+
+}
+
+
+void fax (struct AX *p)
+{
+  T (p->ax[SSIZE_MIN]);                   /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->ax[-1]);                          /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->ax[0]);
+  T (p->ax[SSIZE_MAX - sizeof *p - 1]);
+  T (p->ax[SSIZE_MAX - sizeof *p]);       /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->ax[SSIZE_MAX - sizeof *p + 1]);   /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->ax[SIZE_MAX]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+}
+
+void fa1 (struct A1 *p)
+{
+  T (p->a1[SSIZE_MIN]);                   /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1[-1]);                          /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->a1[0]);
+  T (p->a1[9]);
+  T (p->a1[SSIZE_MAX - sizeof *p - 1]);
+  T (p->a1[SSIZE_MAX - sizeof *p]);       /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1[SSIZE_MAX - sizeof *p + 1]);   /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1[SIZE_MAX]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+}
+
+void fb (struct B *p)
+{
+  T (p->a1x->a1[SSIZE_MIN]);             /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1x->a1[-1]);                    /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->a1x->a1[0]);
+  T (p->a1x->a1[9]);                     /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x->a1[SSIZE_MAX - sizeof *p]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x->a1[SSIZE_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x->a1[SIZE_MAX]);               /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[1].a1[SSIZE_MIN]);            /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1x[1].a1[-1]);                   /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->a1x[1].a1[0]);
+  T (p->a1x[1].a1[9]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[1].a1[SSIZE_MAX - sizeof *p]);/* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[1].a1[SSIZE_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[1].a1[SIZE_MAX]);             /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[2].a1[SSIZE_MIN]);            /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1x[2].a1[-1]);                   /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->a1x[2].a1[0]);
+  T (p->a1x[2].a1[9]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[2].a1[SSIZE_MAX - sizeof *p]);/* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[2].a1[SSIZE_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[2].a1[SIZE_MAX]);             /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[3].a1[SSIZE_MIN]);            /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1x[3].a1[-1]);                   /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->a1x[3].a1[0]);
+  T (p->a1x[3].a1[9]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[9].a1[0]);
+
+  enum { MAX = SSIZE_MAX / sizeof *p->a1x - sizeof *p };
+
+  T (p->a1x[SSIZE_MIN].a1);               /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1x[-1].a1);                      /* { dg-warning "array subscript -1 is below array bounds" } */
+  T (p->a1x[MAX].a1);
+  T (p->a1x[MAX + 2].a1);                 /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[SSIZE_MAX].a1);               /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[SIZE_MAX].a1);                /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[SSIZE_MIN].a1[0]);            /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
+  T (p->a1x[-1].a1[0])                    /* { dg-warning "array subscript -1 is below array bounds" } */;
+  T (p->a1x[MAX - 1].a1[0]);
+  T (p->a1x[MAX].a1[0]);                  /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[MAX + 1].a1[0]);              /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+
+  T (p->a1x[SSIZE_MAX].a1[0]);            /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+  T (p->a1x[SIZE_MAX].a1[0]);             /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */
+}
+
+void f_cststring (int i)
+{
+  T (""[SSIZE_MIN]);                      /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(const )?char *\\\[1]" "string" { xfail lp64 } } */
+  T (""[SSIZE_MIN + 1]);                  /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(const )?char *\\\[1]" "string" } */
+  T (""[-1]);                             /* { dg-warning "array subscript -1 is below array bounds of .(const )?char *\\\[1]" "string" } */
+  T (""[0]);
+  T (""[1]);                              /* { dg-warning "array subscript 1 is above array bounds of .(const )?char *\\\[1]" "string" } */
+  T ("0"[2]);                             /* { dg-warning "array subscript 2 is above array bounds of .(const )?char *\\\[2]" "string" } */
+  T ("012"[2]);
+  T ("012"[3]);
+  T ("012"[4]);                           /* { dg-warning "array subscript 4 is above array bounds of .(const )?char *\\\[4]" "string" } */
+  T ("0123"[SSIZE_MAX]);                  /* { dg-warning "array subscript \[0-9\]+ is above array bounds of .(const )?char *\\\[5]" "string" } */
+  T ("0123"[SIZE_MAX]);                   /* { dg-warning "array subscript \[0-9\]+ is above array bounds of .(const )?char *\\\[5]" "string" } */
+}
+
+void fb_strlen (struct B *p)
+{
+#define strlen __builtin_strlen
+
+  T (strlen (&p->a1x[0].a1[2]));          /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "strlen" } */
+  T (strlen (p->a1x[0].a1 + 2));          /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "strlen" { xfail *-*-* } } */
+}
+
+
+void f_vla (unsigned n)
+{
+  char vla[n];
+
+  T (vla[SSIZE_MIN]);                     /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */
+  T (vla[-1]);                            /* { dg-warning "array subscript -1 is below array bounds" "vla" } */
+  T (vla[0]);
+  T (vla[1]);
+  T (vla[n - 1]);
+  /* It would be nice to diagnose this. */
+  T (vla[n]);                             /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla[SSIZE_MAX]);                     /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-11.c b/gcc/testsuite/gcc.dg/Warray-bounds-11.c
index 089fa00..c9fc461 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-11.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-11.c
@@ -57,19 +57,19 @@ struct h3b {
 
 void foo(int (*a)[3])
 {
-	(*a)[4] = 1;	/* { dg-warning "subscript is above array bound" } */
+	(*a)[4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
 	a[0][0] = 1;	// ok
 	a[1][0] = 1;	// ok
-	a[1][4] = 1;	/* { dg-warning "subscript is above array bound" } */
+	a[1][4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
 
 	int c[3] = { 0 };
 
-	c[4] = 1;	/* { dg-warning "subscript is above array bound" } */
+	c[4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
 
-	e[4] = 1;	/* { dg-warning "subscript is above array bound" } */
+	e[4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
 
 	struct f f;
-	f.f[4] = 1;	/* { dg-warning "subscript is above array bound" } */
+	f.f[4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
 
 	struct h* h = malloc(sizeof(struct h) + 3 * sizeof(int));
 	struct h0* h0 = malloc(sizeof(struct h0) + 3 * sizeof(int));
@@ -78,15 +78,15 @@ void foo(int (*a)[3])
 
 	h->j[4] = 1;	// flexible array member
 	h0->j[4] = 1;	// zero-sized array extension
-	h1->j[4] = 1;	/* { dg-warning "subscript is above array bound" } */
-	h3->j[4] = 1;	/* { dg-warning "subscript is above array bound" } */
+	h1->j[4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
+	h3->j[4] = 1;	/* { dg-warning "subscript 4 is above array bound" } */
 
 	struct h0b* h0b = malloc(sizeof(struct h) + 3 * sizeof(int));
 	struct h1b* h1b = malloc(sizeof(struct h1b) + 3 * sizeof(int));
 	struct h3b* h3b = malloc(sizeof(struct h3b));
 //	h0b->j[4] = 1;
-	h1b->j[4] = 1;;	/* { dg-warning "subscript is above array bound" } */
-	h3b->j[4] = 1;;	/* { dg-warning "subscript is above array bound" } */
+	h1b->j[4] = 1;;	/* { dg-warning "subscript 4 is above array bound" } */
+	h3b->j[4] = 1;;	/* { dg-warning "subscript 4 is above array bound" } */
 
 	// make sure nothing gets optimized away
 	bar(*a);
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-22.c b/gcc/testsuite/gcc.dg/Warray-bounds-22.c
new file mode 100644
index 0000000..ca4b102
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-22.c
@@ -0,0 +1,95 @@
+/* PR tree-optimization/82588 - missing -Warray-bounds on an excessively
+   large index
+   { dg-do compile }
+   { dg-options "-O2 -Warray-bounds -ftrack-macro-expansion=0" }  */
+
+#define SIZE_MAX  __SIZE_MAX__
+#define SSIZE_MAX __PTRDIFF_MAX__
+#define SSIZE_MIN (-SSIZE_MAX - 1)
+
+typedef __PTRDIFF_TYPE__ ssize_t;
+typedef __SIZE_TYPE__    size_t;
+
+extern ssize_t signed_value (void)
+{
+  extern volatile ssize_t signed_value_source;
+  return signed_value_source;
+}
+
+ssize_t signed_range (ssize_t min, ssize_t max)
+{
+  ssize_t val = signed_value ();
+  return val < min || max < val ? min : val;
+}
+
+struct AX { int n; char ax[]; };
+
+struct A1 { int i; char a1[1]; };
+struct B { int i; struct A1 a1x[]; };
+
+void sink (int, ...);
+
+#define T(expr)   sink (0, (expr))
+
+void test_vla (unsigned m, unsigned n)
+{
+  char vla1[m];
+
+  T (vla1[SSIZE_MIN]);                    /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */
+  T (vla1[-1]);                           /* { dg-warning "array subscript -1 is below array bounds" "vla" } */
+  T (vla1[0]);
+  T (vla1[1]);
+  T (vla1[m - 1]);
+  /* It would be nice to diagnose this. */
+  T (vla1[m]);                            /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla1[SSIZE_MAX - 1]);
+  T (vla1[SSIZE_MAX]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+
+  ssize_t i = signed_range (SSIZE_MAX - 1, SSIZE_MAX);
+  T (vla1[i]);
+
+  char vla2[m][n];
+
+  T (vla2[0][SSIZE_MIN]);                 /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */
+  T (vla2[0][-1]);                        /* { dg-warning "array subscript -1 is below array bounds" "vla" } */
+  T (vla2[0][0]);
+  T (vla2[1][1]);
+  T (vla2[m - 1][n - 1]);
+  /* It would be nice to diagnose this. */
+  T (vla2[m][0]);                         /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla2[m + 1][0]);                    /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla2[0][n]);                         /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla2[0][n + 1]);                     /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla2[m][n]);                         /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+  T (vla2[m + 1][n + 1]);                 /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */
+
+  T (vla2[0][SSIZE_MAX]);                 /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+  T (vla2[SSIZE_MAX][0]);                 /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" { xfail *-*-* } } */
+  T (vla2[SSIZE_MAX][SSIZE_MAX]);         /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+
+  struct S256 { char a[256]; } vla3[m];
+
+  T (vla3[SSIZE_MIN].a[0]);               /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */
+  T (vla3[-1].a[0]);                      /* { dg-warning "array subscript -1 is below array bounds" "vla" } */
+  T (vla3[0].a[0]);
+  T (vla3[1].a[0]);
+  T (vla3[m - 1].a[0]);
+  T (vla3[SSIZE_MAX / 256 - 1].a[0]);
+  T (vla3[SSIZE_MAX / 256].a[0]);         /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+
+  i = signed_range (SSIZE_MAX / 256 - 1, SSIZE_MAX);
+  T (vla3[i].a[0]);
+
+  i = signed_range (SSIZE_MAX / 256, SSIZE_MAX);
+  T (vla3[i].a[0]);                       /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+
+  struct VLA { char vla[n]; } x;
+
+  T (x.vla[SSIZE_MIN]);                   /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */
+  T (x.vla[-1]);                          /* { dg-warning "array subscript -1 is below array bounds" "vla" } */
+  T (x.vla[0]);
+  T (x.vla[1]);
+  T (x.vla[n - 1]);
+  T (x.vla[SSIZE_MAX - 1]);
+  T (x.vla[SSIZE_MAX]);                   /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr82596.c b/gcc/testsuite/gcc.dg/pr82596.c
new file mode 100644
index 0000000..5dc67c2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr82596.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/82596 - missing -Warray-bounds on an out-of-bounds
+   index into string literal
+   { dg-do compile }
+   { dg-options "-O2 -Warray-bounds" } */
+
+#define SIZE_MAX  __SIZE_MAX__
+#define SSIZE_MAX __PTRDIFF_MAX__
+#define SSIZE_MIN (-SSIZE_MAX - 1)
+
+void sink (int, ...);
+
+#define T(arg) sink (arg)
+
+void test_cststring (int i)
+{
+  T (""[SSIZE_MIN]);                      /* { dg-warning "below array bounds" "string" { xfail lp64 } } */
+  T (""[SSIZE_MIN + 1]);                  /* { dg-warning "below array bounds" "string" } */
+  T (""[-1]);                             /* { dg-warning "below array bounds" "string" } */
+  T (""[0]);
+  T (""[1]);                              /* { dg-warning "above array bounds" "string" } */
+  T ("0"[2]);                             /* { dg-warning "above array bounds" "string" } */
+  T ("012"[2]);
+  T ("012"[3]);
+  T ("012"[4]);                           /* { dg-warning "above array bounds" "string" } */
+  T ("0123"[SSIZE_MAX]);                  /* { dg-warning "above array bounds" "string" } */
+  T ("0123"[SIZE_MAX]);                   /* { dg-warning "above array bounds" "string" } */
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 2c86b8e..2e7c26c 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimple-walk.h"
 #include "tree-cfg.h"
+#include "tree-dfa.h"
 #include "tree-ssa-loop-manip.h"
 #include "tree-ssa-loop-niter.h"
 #include "tree-ssa-loop.h"
@@ -64,6 +65,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-cfgcleanup.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "builtins.h"
 
 #define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
 
@@ -6675,26 +6677,56 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   low_sub = up_sub = TREE_OPERAND (ref, 1);
   up_bound = array_ref_up_bound (ref);
 
-  /* Can not check flexible arrays.  */
   if (!up_bound
-      || TREE_CODE (up_bound) != INTEGER_CST)
-    return;
+      || TREE_CODE (up_bound) != INTEGER_CST
+      || (warn_array_bounds < 2
+	  && array_at_struct_end_p (ref)))
+    {
+      /* Accesses to trailing arrays via pointers may access storage
+	 beyond the types array bounds.  For such arrays, or for flexible
+	 array members, as well as for other arrays of an unknown size,
+	 replace the upper bound with a more permissive one that assumes
+	 the size of the largest object is PTRDIFF_MAX.  */
+      tree eltsize = array_ref_element_size (ref);
+
+      /* FIXME: Handle VLAs.  */
+      if (TREE_CODE (eltsize) != INTEGER_CST)
+	return;
 
-  /* Accesses to trailing arrays via pointers may access storage
-     beyond the types array bounds.  */
-  if (warn_array_bounds < 2
-      && array_at_struct_end_p (ref))
-    return;
+      tree maxbound = TYPE_MAX_VALUE (ptrdiff_type_node);
+
+      up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
+
+      tree arg = TREE_OPERAND (ref, 0);
+      tree_code code = TREE_CODE (arg);
+      if (code == COMPONENT_REF)
+	{
+	  HOST_WIDE_INT off;
+	  if (tree base = get_addr_base_and_unit_offset (arg, &off))
+	    {
+	      tree size = TYPE_SIZE_UNIT (TREE_TYPE (base));
+	      if (TREE_CODE (size) == INTEGER_CST)
+		up_bound_p1 = int_const_binop (MINUS_EXPR, up_bound_p1, size);
+	    }
+	}
+
+      up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
+				  build_int_cst (ptrdiff_type_node, 1));
+    }
+  else
+    up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
+				   build_int_cst (TREE_TYPE (up_bound), 1));
 
   low_bound = array_ref_low_bound (ref);
-  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
-				 build_int_cst (TREE_TYPE (up_bound), 1));
+
+  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
 
   /* Empty array.  */
   if (tree_int_cst_equal (low_bound, up_bound_p1))
     {
       warning_at (location, OPT_Warray_bounds,
-		  "array subscript is above array bounds");
+		  "array subscript %E is above array bounds of %qT",
+		  low_bound, artype);
       TREE_NO_WARNING (ref) = 1;
     }
 
@@ -6718,7 +6750,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
           && tree_int_cst_le (low_sub, low_bound))
         {
           warning_at (location, OPT_Warray_bounds,
-		      "array subscript is outside array bounds");
+		      "array subscript [%E, %E] is outside array bounds of %qT",
+		      low_sub, up_sub, artype);
           TREE_NO_WARNING (ref) = 1;
         }
     }
@@ -6734,7 +6767,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 	  fprintf (dump_file, "\n");
 	}
       warning_at (location, OPT_Warray_bounds,
-		  "array subscript is above array bounds");
+		  "array subscript %E is above array bounds of %qT",
+		  up_sub, artype);
       TREE_NO_WARNING (ref) = 1;
     }
   else if (TREE_CODE (low_sub) == INTEGER_CST
@@ -6747,7 +6781,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 	  fprintf (dump_file, "\n");
 	}
       warning_at (location, OPT_Warray_bounds,
-		  "array subscript is below array bounds");
+		  "array subscript %E is below array bounds of %qT",
+		  low_sub, artype);
       TREE_NO_WARNING (ref) = 1;
     }
 }
@@ -6802,7 +6837,8 @@ search_for_addr_array (tree t, location_t location)
 	      fprintf (dump_file, "\n");
 	    }
 	  warning_at (location, OPT_Warray_bounds,
-		      "array subscript is below array bounds");
+		      "array subscript %wi is below array bounds of %qT",
+		      idx.to_shwi (), TREE_TYPE (tem));
 	  TREE_NO_WARNING (t) = 1;
 	}
       else if (idx > (wi::to_offset (up_bound)
@@ -6815,7 +6851,8 @@ search_for_addr_array (tree t, location_t location)
 	      fprintf (dump_file, "\n");
 	    }
 	  warning_at (location, OPT_Warray_bounds,
-		      "array subscript is above array bounds");
+		      "array subscript %wu is above array bounds of %qT",
+		      idx.to_uhwi (), TREE_TYPE (tem));
 	  TREE_NO_WARNING (t) = 1;
 	}
     }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]