不应转换无继承关系的指针或引用
12.9 ID_castNoInheritance
无继承关系的指针或引用之间没有逻辑关系,转换意味着设计缺陷或逻辑错误。
示例:
float f = 0;
int* p = (int*)&f; // Non-compliant
(*p)++; // Undefined behavior
基本类型之间没有继承关系,float* 转为 int* 属于逻辑错误,导致标准未定义的行为。
有时为了考察对象内部结构,需要将对象指针转为 unsigned char* 等类型,但这种转换脱离了类型的保护,也会降低代码的可移植性,审计工具不妨通过配置决定是否放过这种转换。
又如:
class A { .... };
class B { .... };
class C: public A, public B { .... };
A* a = new C;
B* b0 = (B*)a; // Non-compliant
B* b1 = reinterpret_cast<B*>(a); // Non-compliant
B* b2 = static_cast<B*>(a); // Compliant, compile-time protected
B* b3 = dynamic_cast<B*>(a); // Compliant, run-time protected
例中 A 与 B 没有继承关系,C 从 A 和 B 继承,指针 a 为 A 类型但实际指向 C 的实例,这种情况下将 a 直接强制转为 B 类型的指针将得到错误的结果,这种问题在实际代码中也很常见。
本规则限制无继承关系的 C 风格类型转换以及 reinterpret_cast 转换,不限制 static_cast 和 dynamic_cast 转换,示例中的 static_cast 转换将得到编译错误从而锁定问题,如果 A 和 B 是多态类型,用 dynamic_cast 会得到正确的结果。
例外:
class V { .... };
class U {
....
public:
operator V*(); // Conversion operator
};
U* u = new U;
V* v0 = (V*)u; // Compliant, but bad
V* v1 = reinterpret_cast<V*>(u); // Still non-compliant
例中 U 和 V 是无继承关系的类,但 U 实现了向 V 的转换运算符,U 和 V 之间存在逻辑关系,这时的 C 风格类型转换可不受本规则限制,但不符合规则 ID_forbidCStyleCast,这种情况仍然不能使用 reinterpret_cast,参见 ID_unsuitableReinterpretCast。
配置
allowWeakerCast: 是否放过与 unsigned char* 的转换
相关
依据
ISO/IEC 9899:1999 6.5(7)-undefined
ISO/IEC 9899:2011 6.5(7)-undefined
ISO/IEC 14882:2003 3.10(15)-undefined
ISO/IEC 14882:2003 4.1(1)-undefined
ISO/IEC 14882:2011 3.10(10)-undefined
ISO/IEC 14882:2011 4.1(1)-undefined
参考
MISRA C 2012 11.3
MISRA C++ 2008 5-2-7
SEI CERT EXP39-C