CodeQL 文档

类型混淆

ID: cpp/type-confusion
Kind: path-problem
Security severity: 9.3
Severity: warning
Precision: medium
Tags:
   - security
   - external/cwe/cwe-843
Query suites:
   - cpp-security-extended.qls
   - cpp-security-and-quality.qls

点击查看 CodeQL 存储库中的查询

C 和 C++ 中的某些强制转换对目标类型没有限制。例如,C 样式的强制转换(如 (MyClass*)p)允许程序员将任何指针 p 强制转换为类型为 MyClass* 的表达式。如果 p 的运行时类型是与 MyClass 不兼容的类型,则会导致未定义的行为。

建议

如果可能,请使用 dynamic_cast 在多态类型之间进行安全地强制转换。如果无法使用 dynamic_cast,请使用 static_cast 来限制编译器允许执行的转换类型。如果无法使用 C++ 样式的强制转换,请仔细检查所有强制转换是否安全。

示例

考虑以下类层次结构,我们定义了一个基类 Shape 和两个派生类 CircleSquare,它们互不兼容

struct Shape {
  virtual ~Shape();

  virtual void draw() = 0;
};

struct Circle : public Shape {
  Circle();

  void draw() override {
    /* ... */
  }

  int getRadius();
};

struct Square : public Shape {
  Square();

  void draw() override {
    /* ... */
  }

  int getLength();
};

以下代码演示了一个类型混淆漏洞,其中程序员假设 p 的运行时类型始终为 Square。但是,如果 pCircle,则强制转换将导致未定义的行为。

void allocate_and_draw_bad() {
  Shape* shape = new Circle;
  // ...
  // BAD: Assumes that shape is always a Square
  Square* square = static_cast<Square*>(shape);
  int length = square->getLength();
}

以下代码通过使用 dynamic_cast 在多态类型之间进行安全地强制转换来修复此漏洞。如果强制转换失败,则 dynamic_cast 将返回一个空指针,可以对其进行检查并进行适当的处理。

void allocate_and_draw_good() {
  Shape* shape = new Circle;
  // ...
  // GOOD: Dynamically checks if shape is a Square
  Square* square = dynamic_cast<Square*>(shape);
  if(square) {
    int length = square->getLength();
  } else {
    // handle error
  }
}

参考资料

  • ©GitHub 公司
  • 条款
  • 隐私