[PATCH] Fix ubsan/bounds-2.c

Marek Polacek polacek@redhat.com
Wed Jun 25 13:37:00 GMT 2014


On Wed, Jun 25, 2014 at 02:49:56PM +0200, Jakub Jelinek wrote:
> On Wed, Jun 25, 2014 at 02:40:40PM +0200, Marek Polacek wrote:
> > On IRC Ramana reported that on ARM ubsan/bounds-2.c test fails with -O0,
> > since we write to out-of-bounds location and probably rewrite the
> > frame pointer stored in the stack.  This patch removes such stores
> > and adds some asm magic so the compiler doesn't optimize loads away as
> > uninitialized memory read.
> > 
> > Ramana, does this patch help on ARM?
> > Tested x86_64-unknown-linux-gnu, ok for trunk?
> 
> What about bounds-5.c ?  Also, do you have any tests for negative indexes?

Ok, adjusted bounds-5.c as well.  New test for negative indexes added.

make -C gcc check-g{cc,++} RUNTESTFLAGS='--target_board=unix\{-m32,-m64\} ubsan.exp'
passes on x86_64-linux.

2014-06-25  Marek Polacek  <polacek@redhat.com>

	* c-c++-common/ubsan/bounds-2.c: Adjust dg-output.
	(fn1): Remove store to out-of-bounds location.  Add memory barrier.
	(fn2): Likewise.
	(fn5): Likewise.
	(fn6): Likewise.
	(fn7): Likewise.
	(fn8): Likewise.
	(fn9): Likewise.
	(fn11): Likewise.
	* c-c++-common/ubsan/bounds-5.c (fn1): Remove store to out-of-bounds
	location.  Add memory barrier.
	(fn2): Likewise.
	(fn3): Likewise.
	(fn4): Likewise.
	(fn5): Likewise.
	* c-c++-common/ubsan/bounds-7.c: New test.

diff --git gcc/testsuite/c-c++-common/ubsan/bounds-2.c gcc/testsuite/c-c++-common/ubsan/bounds-2.c
index 95f77c2..3a24d40 100644
--- gcc/testsuite/c-c++-common/ubsan/bounds-2.c
+++ gcc/testsuite/c-c++-common/ubsan/bounds-2.c
@@ -22,7 +22,7 @@ static void __attribute__ ((noinline, noclone))
 fn1 (void)
 {
   volatile int a[5];
-  a[5] = 1;
+  asm ("" : : "r" (&a[5]) : "memory");
   a[2] = a[5];
 }
 
@@ -30,9 +30,11 @@ static void __attribute__ ((noinline, noclone))
 fn2 (void)
 {
   volatile int a[5];
+  volatile int j;
   int i = 5;
   int *p = &i;
-  a[*p] = 1;
+  asm ("" : : "r" (&a[*p]) : "memory");
+  j = a[*p];
 }
 
 static void __attribute__ ((noinline, noclone))
@@ -54,7 +56,7 @@ fn5 (void)
 {
   int i = 5;
   volatile int a[i];
-  a[i] = 1;
+  asm ("" : : "r" (&a[i]) : "memory");
   a[2] = a[i];
 }
 
@@ -63,29 +65,32 @@ fn6 (void)
 {
   int i = 5;
   volatile int a[i];
+  volatile int j;
   fn_p (a[i]);
-  a[foo_5 ()] = 1;
+  asm ("" : : "r" (&a[foo_5 ()]) : "memory");
+  j = a[foo_5 ()];
 }
 
 static void __attribute__ ((noinline, noclone))
 fn7 (void)
 {
-  int n = 5, i;
+  int n = 5;
+  volatile int i;
   volatile int c[n][n][n];
-  c[5][2][2] = 2;
-  c[2][5][2] = 2;
-  c[2][2][5] = 2;
+  asm ("" : : "r" (&c[5][2][2]) : "memory");
   i = c[5][2][2];
+  asm ("" : : "r" (&c[2][5][2]) : "memory");
   i = c[2][5][2];
+  asm ("" : : "r" (&c[2][2][5]) : "memory");
   i = c[2][2][5];
 }
 
 static void __attribute__ ((noinline, noclone))
 fn8 (void)
 {
-  int i = 5;
+  volatile int i;
   volatile struct S s;
-  s.a[10] = 1;
+  asm ("" : : "r" (&s.a[10]) : "memory");
   i = s.a[10];
 }
 
@@ -93,7 +98,7 @@ static void __attribute__ ((noinline, noclone))
 fn9 (void)
 {
   long int *volatile d[10][5];
-  d[10][0] = 0;
+  asm ("" : : "r" (&d[10][0]) : "memory");
   d[8][3] = d[10][0];
 }
 
@@ -115,7 +120,7 @@ static void __attribute__ ((noinline, noclone))
 fn11 (void)
 {
   char ***volatile f[5];
-  f[5] = 0;
+  asm ("" : : "r" (&f[5]) : "memory");
   f[2] = f[5];
 }
 
@@ -148,21 +153,16 @@ main (void)
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 10 out of bounds for type 'long int \\\*\\\[10\\\]\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 10 out of bounds for type 'long int \\\*\\\[10\\\]\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'char \\\*\\\*\\\*\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'char \\\*\\\*\\\*\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git gcc/testsuite/c-c++-common/ubsan/bounds-5.c gcc/testsuite/c-c++-common/ubsan/bounds-5.c
index 7b7d76d..68f0648 100644
--- gcc/testsuite/c-c++-common/ubsan/bounds-5.c
+++ gcc/testsuite/c-c++-common/ubsan/bounds-5.c
@@ -9,11 +9,16 @@ void
 fn1 (void)
 {
   volatile struct S { char a[1]; char b; } s;
-  s.a[0] = 1; // OK
-  s.a[1] = 2; // error
+  volatile int i;
+  asm ("" : : "r" (&s.a[0]) : "memory");
+  i = s.a[0]; // OK
+  asm ("" : : "r" (&s.a[1]) : "memory");
+  i = s.a[1]; // error
   volatile struct S *p = &s;
-  p->a[0] = 1; // OK
-  p->a[1] = 1; // error
+  asm ("" : : "r" (&p->a[0]) : "memory");
+  i = p->a[0]; // OK
+  asm ("" : : "r" (&p->a[1]) : "memory");
+  i = p->a[1]; // error
 }
 
 __attribute__ ((noinline, noclone))
@@ -22,11 +27,16 @@ fn2 (void)
 {
   struct S { int c; char d[4]; };
   volatile struct T { int e; struct S f; int g; } t;
-  t.f.d[3] = 1; // OK
-  t.f.d[4] = 1; // error
+  volatile int i;
+  asm ("" : : "r" (&t.f.d[3]) : "memory");
+  i = t.f.d[3]; // OK
+  asm ("" : : "r" (&t.f.d[4]) : "memory");
+  i = t.f.d[4]; // error
   volatile struct T *p = &t;
-  p->f.d[3] = 1; // OK
-  p->f.d[4] = 1; // error
+  asm ("" : : "r" (&p->f.d[3]) : "memory");
+  i = p->f.d[3]; // OK
+  asm ("" : : "r" (&p->f.d[4]) : "memory");
+  i = p->f.d[4]; // error
 }
 
 __attribute__ ((noinline, noclone))
@@ -34,11 +44,16 @@ void
 fn3 (void)
 {
   volatile struct S { char b; char a[1]; } s;
-  s.a[0] = 1; // OK
-  s.a[1] = 1; // error
+  volatile int i;
+  asm ("" : : "r" (&s.a[0]) : "memory");
+  i = s.a[0]; // OK
+  asm ("" : : "r" (&s.a[1]) : "memory");
+  i = s.a[1]; // error
   volatile struct S *p = &s;
-  p->a[0] = 1; // OK
-  p->a[1] = 1; // error in strict mode
+  asm ("" : : "r" (&p->a[0]) : "memory");
+  i = p->a[0]; // OK
+  asm ("" : : "r" (&p->a[1]) : "memory");
+  i = p->a[1]; // error in strict mode
 }
 
 __attribute__ ((noinline, noclone))
@@ -47,11 +62,16 @@ fn4 (void)
 {
   volatile struct S { char b; char a[1]; } s;
   volatile struct T { struct S s; int i; } t;
-  t.s.a[0] = 1; // OK
-  t.s.a[1] = 1; // error
+  volatile int i;
+  asm ("" : : "r" (&t.s.a[0]) : "memory");
+  i = t.s.a[0]; // OK
+  asm ("" : : "r" (&t.s.a[1]) : "memory");
+  i = t.s.a[1]; // error
   volatile struct T *pt = &t;
-  pt->s.a[0] = 1; // OK
-  pt->s.a[1] = 1; // error
+  asm ("" : : "r" (&pt->s.a[0]) : "memory");
+  i = pt->s.a[0]; // OK
+  asm ("" : : "r" (&pt->s.a[1]) : "memory");
+  i = pt->s.a[1]; // error
 }
 
 __attribute__ ((noinline, noclone))
@@ -60,11 +80,16 @@ fn5 (void)
 {
   volatile struct S { char b; char a[1]; } s;
   volatile struct U { int a; struct S s; } u;
-  u.s.a[0] = 1; // OK
-  u.s.a[1] = 1; // error
+  volatile int i;
+  asm ("" : : "r" (&u.s.a[0]) : "memory");
+  i = u.s.a[0]; // OK
+  asm ("" : : "r" (&u.s.a[1]) : "memory");
+  i = u.s.a[1]; // error
   volatile struct U *pu = &u;
-  pu->s.a[0] = 1; // OK
-  pu->s.a[1] = 1; // error in strict mode
+  asm ("" : : "r" (&pu->s.a[0]) : "memory");
+  i = pu->s.a[0]; // OK
+  asm ("" : : "r" (&pu->s.a[1]) : "memory");
+  i = pu->s.a[1]; // error in strict mode
 }
 
 int
diff --git gcc/testsuite/c-c++-common/ubsan/bounds-7.c gcc/testsuite/c-c++-common/ubsan/bounds-7.c
index e69de29..266b53b 100644
--- gcc/testsuite/c-c++-common/ubsan/bounds-7.c
+++ gcc/testsuite/c-c++-common/ubsan/bounds-7.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+
+/* Test negative bounds.  */
+
+struct S { int a[10]; };
+
+__attribute__ ((noinline, noclone))
+void
+fn1 (void)
+{
+  volatile int i;
+  int m = -1;
+  volatile int a[7];
+  asm ("" : : "r" (&a[-1]) : "memory");
+  i = a[-1];
+  asm ("" : : "r" (&a[m]) : "memory");
+  i = a[m];
+}
+
+__attribute__ ((noinline, noclone))
+void
+fn2 (void)
+{
+  volatile int i;
+  int m = 7;
+  volatile int a[m];
+  asm ("" : : "r" (&a[-1]) : "memory");
+  i = a[-1];
+}
+
+__attribute__ ((noinline, noclone))
+void
+fn3 (void)
+{
+  volatile int i;
+  volatile struct S s;
+  asm ("" : : "r" (&s.a[-1]) : "memory");
+  i = s.a[-1];
+}
+
+int
+main (void)
+{
+  fn1 ();
+  fn2 ();
+  fn3 ();
+  return 0;
+}
+
+/* { dg-output "index -1 out of bounds for type 'int \\\[7\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[7\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */

	Marek



More information about the Gcc-patches mailing list