Retro68/gcc/libvtv/testsuite/libvtv.cc/thunk_vtable_map_attack.cc
2014-09-21 19:33:12 +02:00

114 lines
2.4 KiB
C++

// { dg-do run }
#include <assert.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using std::ofstream;
using std::ifstream;
using std::ios;
struct A {
A():value(123) {}
int value;
virtual int access() { return this->value; }
};
struct B {
B():value(456) {}
int value;
virtual int access() { return this->value; }
};
struct C : public A, public B {
C():better_value(789) {}
int better_value;
virtual int access() { return this->better_value; }
};
struct D: public C {
D():other_value(987) {}
int other_value;
virtual int access() { return this->other_value; }
};
volatile static int signal_count = 0;
sigjmp_buf before_segv;
static void
handler(int sig, siginfo_t *si, void *unused)
{
/*
printf("Got SIGSEGV at address: 0x%lx\n",
(long) si->si_addr);
*/
signal_count++;
/* You are not supposed to longjmp out of a signal handler but it seems
to work for this test case and it simplifies it */
siglongjmp(before_segv, 1);
/* exit(1); */
}
/* Access one of the vtable_map variables generated by this .o */
extern void * _ZN4_VTVI1BE12__vtable_mapE;
/* Access one of the vtable_map variables generated by libstdc++ */
extern void * _ZN4_VTVISt8ios_baseE12__vtable_mapE;
int use(B *b)
{
int ret;
ret = sigsetjmp(before_segv, 1);
if (ret == 0)
{
/* This should generate a segmentation violation. ie: at this point it should
be protected */
_ZN4_VTVI1BE12__vtable_mapE = 0;
}
assert(ret == 1 && signal_count == 1);
ret = sigsetjmp(before_segv, 1);
if (ret == 0)
{
/* Try to modify one of the vtable_map variables in the stdc++ library.
This should generate a segmentation violation. ie: at this point it
should be protected */
_ZN4_VTVISt8ios_baseE12__vtable_mapE = 0;
}
assert(ret == 1 && signal_count == 2);
return b->access();
}
void myread(std::istream * in)
{
char input_str[50] = "\0";
if (in->good())
(*in) >> input_str;
std::cout << input_str << std::endl;
delete in;
}
int main()
{
ifstream * infile = new ifstream("./thunk_vtable_map_attack.cpp");
myread(infile);
/* Set up handler for SIGSEGV. */
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
assert(0);
C c;
assert(use(&c) == 789);
return 0;
}