fork download
  1. #include <vector>
  2. #include <iostream>
  3.  
  4. struct A {
  5. int m;
  6. A() {
  7. m = 'A';
  8. }
  9. friend std::ostream& operator<<(std::ostream&os, A a);
  10. };
  11.  
  12. std::ostream& operator<<(std::ostream&os, A a) {
  13. os << a.m;
  14. return os;
  15. }
  16.  
  17. int main()
  18. {
  19. std::vector<int> a;
  20. a.push_back(0);
  21. a.pop_back();
  22. int & b = *a.begin(); // same as a.front(); in g++ 4.7
  23. std::cout << b << std::endl; // 0
  24.  
  25. // now say we store something like 42 in a vector
  26. std::vector<int> c;
  27. c.push_back(42);
  28. c.pop_back();
  29. int & d = c.front();
  30. std::cout << d << std::endl; // 42
  31.  
  32. // now let's corrupt the stack
  33. int *e = &c[0];
  34. *e = 17;
  35.  
  36. // ta-da
  37. std::cout << d << std::endl; // 17
  38.  
  39. // now let's corrupt the stack of vector<int> a in evil ways..
  40. double *f = reinterpret_cast<double*>(&a[0]);
  41. *f = 3.14;
  42.  
  43. // ta-da again!
  44. std::cout << *reinterpret_cast<double*>(&b) << std::endl; // 3.14
  45.  
  46. // or from a directly
  47. std::cout << *reinterpret_cast<double*>(&a.front()) << std::endl; // 3.14
  48.  
  49. // but wait..!
  50. a.push_back(23);
  51. std::cout << b << std::endl; // 23 -- ZOMG! HOW?!
  52.  
  53. a.pop_back();
  54. std::cout << b << std::endl; // 23 again!
  55.  
  56. // more shenanigans
  57. A a2;
  58. a.push_back(*reinterpret_cast<int*>(&a2.m));
  59. std::cout << *reinterpret_cast<char*>(&*a.begin()) << std::endl; // A
  60.  
  61. a.pop_back();
  62. a.push_back(*reinterpret_cast<char*>(&a2));
  63. std::cout << (char)*a.begin() << std::endl; // A again!
  64.  
  65. // Conclusions: the stack is fun!
  66. }
  67.  
Success #stdin #stdout 0.01s 2816KB
stdin
Standard input is empty
stdout
0
42
17
3.14
3.14
23
23
A
A