This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/69482] Writing through pointers to volatile not always preserved
- From: "rguenther at suse dot de" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 27 Jan 2016 08:36:27 +0000
- Subject: [Bug rtl-optimization/69482] Writing through pointers to volatile not always preserved
- Auto-submitted: auto-generated
- References: <bug-69482-4 at http dot gcc dot gnu dot org/bugzilla/>
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.