OOP55-CPP. 不要使用成员指针运算符来访问不存在的成员
原文链接:
OOP55-CPP. Do not use pointer-to-member operators to access nonexistent members
成员指针运算符 .* 和 ->* 被用于获取一个对象或者函数,像是访问底层对象的成员一样。例如,下述代码和调用对象 o
的成员函数 f()
功能上是等价的。
1 | struct S { |
o.f()
的调用方式在编译器通过类成员访问来查找对象 o
的 S::f()
的函数地址。(o.*pm)()
的调用方式通过成员指针运算符 .*
来调用 pm
指向的地址上的函数。两种情况中,对象 o
都是成员函数 S::f()
的隐式 this
对象。
C++ 标准, [expr.mptr.oper], 段 4 [ISO/IEC 14882-2014], 陈述如下:
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.缩写成
E1.*E2
的 pm-expression.*cast-expression 被称为对象表达式。如果E1
的动态类型不包含E2
引用的成员,则该行为是未定义的。
形如 E1->*E2
的成员指针表达式被转换为等价形式,(*(E1)).*E2
, 所以其中任一形式的成员指针表达式的使用均表现为 undefined behavior.
进一步地, C++ 标准, [expr.mptr.oper], 段 6, 部分陈述如下:
If the second operand is the null pointer to member value, the behavior is undefined.
如果第二个操作对象是空指针,该行为是未定义的。
在第一个操作数的动态类型不包含第二个操作数所引用的成员时,不要使用成员指针表达式,包括第二个操作数是一个空指针成员。
不合规代码示例
在这个不合规的代码示例中,从 D::g
中获取的一个成员指针对象被向上转换为 B::*
。当在动态类型为 D
的对象上调用时,成员指针调用是良好的。然而,若动态类型的潜在对象是 B
,则导致 未定义行为,undefined behavior.
1 | struct B { |
合规方案
在这个合规方案中,向上转换被移除,使原始代码表现为 病态,ill-formed ,突出 B::g()
不存在的潜在问题。该兼容方案假设程序员的意图是要使用底层对象正确的动态类型。
1 | struct B { |
不合规代码示例
在这个不合规的代码示例中,传入空成员指针作为成员指针表达式的第二个操作数,造成 未定义行为,undefined behavior.
1 | struct B { |
合规方案
在这个合规方案中,gptr
被正确初始化为一个合法的成员指针,而不是默认的 nullptr
.
1 | struct B { |
Risk Assessment
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
OOP55-CPP | High | Probable | High | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Astrée | 20.10 | overflow_upon_dereference invalid_function_pointer | |
Axivion Bauhaus Suite | 7.2.0 | CertC++-OOP55 | |
Helix QAC | 2022.1 | C++2810, C++2811, C++2812, C++2813, C++2814 | |
Klocwork | 2022.1 | CERT.OOP.PTR_MEMBER.NO_MEMBER | |
Parasoft C/C++test | 2021.2 | **CERT_CPP-OOP55-a ** | A cast shall not convert a pointer to a function to any other pointer type, including a pointer to function type |
Parasoft Insure++ | Runtime detection | ||
PRQA QA-C++ | 4.4 | 2810, 2811, 2812, 2813, 2814 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
This rule is a subset of EXP34-C. Do not dereference null pointers.
Bibliography
[ISO/IEC 14882-2014] | Subclause 5.5, “Pointer-to-Member Operators” |
---|---|
本文标题:OOP55-CPP. 不要使用成员指针运算符来访问不存在的成员
文章作者:xwnb
发布时间:2022-04-23
最后更新:2023-04-17
原始链接:https://xwnb.github.io/posts/3554254475/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!并保留本声明。感谢您的阅读和支持!
分享