2 /* { dg-options "-fstrub=strict" } */
3 /* { dg-require-effective-target alloca } */
4 /* { dg-require-effective-target strub } */
6 /* Check that a non-strub function leaves a string behind in the stack, and that
7 equivalent strub functions don't. */
9 const char test_string
[] = "\x55\xde\xad\xbe\xef\xc0\x1d\xca\xfe\x55\xaa";
11 static inline __attribute__ ((__always_inline__
, __strub__ ("callable")))
15 int len
= sizeof (test_string
);
16 char *s
= (char *) __builtin_alloca (len
);
17 __builtin_strcpy (s
, test_string
);
19 return (char *) __builtin_stack_address ();
22 static inline __attribute__ ((__always_inline__
))
24 look_for_string (char *e
)
26 char *p
= (char *) __builtin_stack_address ();
38 for (char *re
= e
- sizeof (test_string
); p
< re
; p
++)
39 for (int i
= 0; p
[i
] == test_string
[i
]; i
++)
40 if (i
== sizeof (test_string
) - 1)
46 static __attribute__ ((__noinline__
, __noclone__
))
50 return leak_string ();
53 static __attribute__ ((__strub__ ("at-calls")))
57 return leak_string ();
60 static __attribute__ ((__strub__ ("internal")))
64 return leak_string ();
69 /* Since these test check stack contents above the top of the stack, an
70 unexpected asynchronous signal or interrupt might overwrite the bits we
71 expect to find and cause spurious fails. Tolerate one such overall
72 spurious fail by retrying. */
74 while (!look_for_string (callable ()))
75 if (!i
--) __builtin_abort ();
76 while (look_for_string (at_calls ()))
77 if (!i
--) __builtin_abort ();
78 while (look_for_string (internal ()))
79 if (!i
--) __builtin_abort ();