The vulnerability as described in ISO/IEC TR 24772-1:2019 clause 6.43 exists in C++ for virtual functions, except for constructors and destructors which are not dispatching. An example of the infinite recursion is:
#include <iostream>
class A {
public:
virtual void f() { std::cout << "A::f()\n"; }
virtual void g() { std::cout << "A::g()\n"; A::f(); } //call to f() will not dispatch.
virtual void h() { std::cout << "A::h()\n"; }
virtual void i() { std::cout << "A::i()\n"; h(); } //call to h() will dispatch
//showing the vulnerability
};
class B : public A {
public:
void f() override { std::cout << "B::f()\n"; g(); }
void h() override { std::cout << "B::h()\n"; i(); }
};
int main() {
B b;
A * pA = &b;// no problem
pA->f(); std::cout << "---\n";
// infinite recursion
pA->h(); }
In C++, the call to a member function can be qualified, as shown in the above example, and avoids the vulnerability.
To avoid the vulnerability or mitigate its ill effects, C++ software developers can:
At a call site, consider whether virtual dispatch is desired: if not, construct the call using the qualified name.
Be suspicious of any call from a virtual member function of the derived class to any member function of any of its base classes.