The pointer-to-member operators .* and ->* are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function f() on the object o:
...
The C++ Standard, [expr.mptr.oper], paragraph 4 , states [ISO/IEC 14882-2014], states :
Abbreviating pm-expression.*cast-expression as
E1.*E2,E1is called the object expression. If the dynamic type ofE1does not contain the member to whichE2refers, the behavior is undefined.
...
Further, the C++ Standard, [expr.mptr.oper], paragraph 6, states, in part:
If the second operand is the null pointer to member value, the behavior is undefined.
...
In this noncompliant code example, a pointer-to-member object is obtained from D::g, but upcast to be a B::*. When called on an object whose dynamic type is D, the pointer-to-member call is well - defined. However, in this noncompliant code example, the dynamic type of the underlying object is B, resulting in undefined behavior:
| Code Block | ||||
|---|---|---|---|---|
| ||||
struct B {
virtual ~B() = default;
};
struct D : B {
virtual ~D() = default;
virtual void g() { /* ... */ }
};
void f() {
B *b = new B;
// ...
void (B::*gptr)() = static_cast<void(B::*)()>(&D::g);
(b->*gptr)();
delete b;
}
|
...
In this compliant solution, the upcast is removed, rendering the initial code ill-formed . This emphasizes and emphasizing the underlying problem: that B::g() does not exist. This compliant solution assumed assumes the programmer intent was to use the correct dynamic type for the underlying object:
...
In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in undefined behavior:
| Code Block | ||||
|---|---|---|---|---|
| ||||
struct B {
virtual ~B() = default;
};
struct D : B {
virtual ~D() = default;
virtual void g() { /* ... */ }
};
static void (D::*gptr)();
void call_memptr(D *ptr) {
(ptr->*gptr)();
}
void f() {
D *d = new D;
call_memptr(d);
delete d;
} |
...
In this compliant solution, gptr is properly initialized to a valid pointer-to-member value , instead of to the default value of nullptr:
...
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
|
Bibliography
| [ISO/IEC 14882-2014] | 5.5, "Pointer-to-Member Operators" |
...