1 /* { dg-do run } */
2 /* { dg-require-effective-target hwaddress_exec } */
3 
4 /*
5    Tests of nested funtions are:
6     0) Accessing closed over variables works.
7     1) Accesses outside of variables is caught.
8     2) Accessing variable out of scope is caught.
9 
10     Here we test that accessing closed over variables works.
11  */
12 
13 /* We need a second layer of indirection so that GCC doesn't notice we're
14    returning the address of a local variable and put 0 in it's place.  */
15 __attribute__((noinline))
Ident(void * x)16 int *Ident(void *x) {
17   return x;
18 }
19 
20 int __attribute__ ((noinline))
intermediate(void (* f)(int,char),char num)21 intermediate (void (*f) (int, char),
22 	      char num)
23 {
24   if (num == 1)
25     /* NOTE: We need to overrun by an amount greater than the "extra data" in a
26        nonlocal goto structure.  The entire structure is allocated on the stack
27        with a single tag, which means hwasan can't tell if a closed-over buffer
28        was overrun by an amount small enough that the access was still to some
29        data in that nonlocal goto structure.  */
30     f (100, 100);
31   else
32     f (3, 100);
33   /* Just return something ... */
34   return num % 3;
35 }
36 
37 int* __attribute__ ((noinline))
nested_function(char num)38 nested_function (char num)
39 {
40   int big_array[16];
41   int other_array[16];
42   void store (int index, char value)
43     { big_array[index] = value; }
44   return Ident(&other_array[intermediate (store, num)]);
45 }
46 
47 #ifndef MAIN
main()48 int main ()
49 {
50   nested_function (0);
51   return 0;
52 }
53 #endif
54