https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69482
--- Comment #5 from rguenther at suse dot de <rguenther at suse dot de> --- On Wed, 27 Jan 2016, wipedout at yandex dot ru wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69482 > > --- Comment #4 from wipedout at yandex dot ru --- > Okay, suppose we have the following scenario. There's a third party library > with an encryption function like this: > > void encrypt( void* data, void* key ); > > That function is compiled into as a static library and we cannot recompile it. > We know that the function copies the key onto the stack and fails to overwrite > it. > > So we want to overwrite the stack after that function. Here's what we > could do: > > > void overwrite() > { > char array[SIZE]; > memset_s( array, SIZE ); > } > > void usefulFunction() > { > encrypt( something, key ); > overwrite(); > } > > This would work the following way: first, `encrypt()` runs and leaves data on > the stack. Then `overwrite()` runs, allocates an array which very likely > overlaps with the area where `encrypt()` left the data and overwrites that > array. > > This "array is not used" optimization heuristic equally applies to the array > in > overwrite() and a later version of gcc may decide that no matter how the array > is allocated it's not used and therefore no need to overwrite it. > > Yes, I know that the trick relies on undefined behavior in the first place. well, it doesn't rely on undefined behavior. It relies on the compiler not performing valid optimizations on it ;) All it takes to make it work is declare 'array' itself volatile and prevent the compiler from inlining 'overwrite' (otherwise the stack-overwriting wouldn't work). #include <stddef.h> #include <string.h> static void __attribute__((noinline)) overwrite (size_t n) { volatile char array[n]; unsigned i; for (i = 0; i < n; ++i) array[i] = 0; } extern void foo (); void test() { foo (); overwrite (1024); } works for me. It may not be very fast (volatile char stores) though.