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
,E1
is called the object expression. If the dynamic type ofE1
does not contain the member to whichE2
refers, 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" |
...