| /* { dg-do run } */ |
| /* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds" } */ |
| |
| /* Test flexible array member-like arrays. Normal flexible array members |
| are tested in bounds-1.c. Test non-strict mode. */ |
| |
| __attribute__ ((noinline, noclone)) |
| void |
| fn1 (void) |
| { |
| volatile struct S { char a[1]; char b; } s; |
| volatile int i; |
| asm ("" : : "r" (&s.a) : "memory"); |
| i = s.a[0]; // OK |
| asm ("" : : "r" (&s.a) : "memory"); |
| i = s.a[1]; // error |
| volatile struct S *p = &s; |
| asm ("" : : "r" (&p->a) : "memory"); |
| i = p->a[0]; // OK |
| asm ("" : : "r" (&p->a) : "memory"); |
| i = p->a[1]; // error |
| } |
| |
| __attribute__ ((noinline, noclone)) |
| void |
| fn2 (void) |
| { |
| struct S { int c; char d[4]; }; |
| volatile struct T { int e; struct S f; int g; } t; |
| volatile int i; |
| asm ("" : : "r" (&t.f.d) : "memory"); |
| i = t.f.d[3]; // OK |
| asm ("" : : "r" (&t.f.d) : "memory"); |
| i = t.f.d[4]; // error |
| volatile struct T *p = &t; |
| asm ("" : : "r" (&p->f.d) : "memory"); |
| i = p->f.d[3]; // OK |
| asm ("" : : "r" (&p->f.d) : "memory"); |
| i = p->f.d[4]; // error |
| } |
| |
| __attribute__ ((noinline, noclone)) |
| void |
| fn3 (void) |
| { |
| volatile struct S { char b; char a[1]; } s; |
| volatile int i; |
| asm ("" : : "r" (&s.a) : "memory"); |
| i = s.a[0]; // OK |
| asm ("" : : "r" (&s.a) : "memory"); |
| i = s.a[1]; // error |
| volatile struct S *p = &s; |
| asm ("" : : "r" (&p->a) : "memory"); |
| i = p->a[0]; // OK |
| asm ("" : : "r" (&p->a) : "memory"); |
| i = p->a[1]; // error in strict mode |
| } |
| |
| __attribute__ ((noinline, noclone)) |
| void |
| fn4 (void) |
| { |
| volatile struct S { char b; char a[1]; } s; |
| volatile struct T { struct S s; int i; } t; |
| volatile int i; |
| asm ("" : : "r" (&t.s.a) : "memory"); |
| i = t.s.a[0]; // OK |
| asm ("" : : "r" (&t.s.a) : "memory"); |
| i = t.s.a[1]; // error |
| volatile struct T *pt = &t; |
| asm ("" : : "r" (&pt->s.a) : "memory"); |
| i = pt->s.a[0]; // OK |
| asm ("" : : "r" (&pt->s.a) : "memory"); |
| i = pt->s.a[1]; // error |
| } |
| |
| __attribute__ ((noinline, noclone)) |
| void |
| fn5 (void) |
| { |
| volatile struct S { char b; char a[1]; } s; |
| volatile struct U { int a; struct S s; } u; |
| volatile int i; |
| asm ("" : : "r" (&u.s.a) : "memory"); |
| i = u.s.a[0]; // OK |
| asm ("" : : "r" (&u.s.a) : "memory"); |
| i = u.s.a[1]; // error |
| volatile struct U *pu = &u; |
| asm ("" : : "r" (&pu->s.a) : "memory"); |
| i = pu->s.a[0]; // OK |
| asm ("" : : "r" (&pu->s.a) : "memory"); |
| i = pu->s.a[1]; // error in strict mode |
| } |
| |
| int |
| main (void) |
| { |
| fn1 (); |
| fn2 (); |
| fn3 (); |
| fn4 (); |
| fn5 (); |
| return 0; |
| } |
| |
| /* { dg-output "index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ |
| /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'" } */ |