Changing the vtable pointer

Most compilers implement dynamic binding by using a vtable whose pointer resides at the beginning of each object’s memory footprint (something along the lines of [vtable-pointer|..members..], if we are not considering virtual inheritance).

Keeping this idea in mind, why don’t we go ahead and attempt to change that vtable pointer?

#include <iostream>
using std::cout;

struct A {
    virtual void f () { cout << "a:" << n; }
    A () : n(1) {}
    int n;
};

struct B : A {
    void f () { cout << "b:" << n; }
    B () { n = 2; }
};

int main () {
    A *a = new A();
    A *b = new B();
    // lets change a's vtable to b's
    *reinterpret_cast<void**>(a) = 
          *reinterpret_cast<void**>(b);
    a->f(); // hurray, B::f() is invoked!
}

Notice we surely did not touch the object itself, since the member did not change.

One extra thing i would like to mention is that i have tried to change specific entries inside the vtable, but the compiler marks that memory area as read-only and therefore throws an exception whenever modification attempts are made. Here is the attempted piece of code:

#include <iostream>
using std::cout;

struct A {
    virtual void f () { cout << "f"; }
    virtual void g () { cout << "g"; }
};

int main () {
    A *a = new A();
 
    void **vtable = *reinterpret_cast<void***>(a);
    vtable[0] = vtable[1];

    a->f();
}

This change to the vtable would make the call to f() actually invoke g().

Leave a Reply