#include <vector>
#include <iostream>
struct A {
int m;
A() {
m = 'A';
}
friend std::ostream& operator<<(std::ostream&os, A a);
};
std::ostream& operator<<(std::ostream&os, A a) {
os << a.m;
return os;
}
int main()
{
std::vector<int> a;
a.push_back(0);
a.pop_back();
int & b = *a.begin(); // same as a.front(); in g++ 4.7
std::cout << b << std::endl; // 0
// now say we store something like 42 in a vector
std::vector<int> c;
c.push_back(42);
c.pop_back();
int & d = c.front();
std::cout << d << std::endl; // 42
// now let's corrupt the stack
int *e = &c[0];
*e = 17;
// ta-da
std::cout << d << std::endl; // 17
// now let's corrupt the stack of vector<int> a in evil ways..
double *f = reinterpret_cast<double*>(&a[0]);
*f = 3.14;
// ta-da again!
std::cout << *reinterpret_cast<double*>(&b) << std::endl; // 3.14
// or from a directly
std::cout << *reinterpret_cast<double*>(&a.front()) << std::endl; // 3.14
// but wait..!
a.push_back(23);
std::cout << b << std::endl; // 23 -- ZOMG! HOW?!
a.pop_back();
std::cout << b << std::endl; // 23 again!
// more shenanigans
A a2;
a.push_back(*reinterpret_cast<int*>(&a2.m));
std::cout << *reinterpret_cast<char*>(&*a.begin()) << std::endl; // A
a.pop_back();
a.push_back(*reinterpret_cast<char*>(&a2));
std::cout << (char)*a.begin() << std::endl; // A again!
// Conclusions: the stack is fun!
}