CodeQL 文档

已过期容器的迭代器

ID: cpp/iterator-to-expired-container
Kind: problem
Security severity: 8.8
Severity: warning
Precision: medium
Tags:
   - reliability
   - security
   - external/cwe/cwe-416
   - external/cwe/cwe-664
Query suites:
   - cpp-security-extended.qls
   - cpp-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

在容器的生命周期结束之后使用容器拥有的迭代器会导致未定义的行为。这是因为当容器被销毁时,迭代器可能失效,解除引用失效的迭代器会导致未定义的行为。由于 C++ 对临时对象生命周期的复杂规则及其扩展,这些问题可能难以发现。

建议

当预期在容器生命周期结束之后使用迭代器时,切勿为临时容器创建迭代器。

示例

生命周期扩展规则确保 lifetime_of_temp_extended 中的代码是定义明确的。这是因为 get_vector 返回的临时容器的生命周期扩展到了循环的末尾。但是,在 C++23 之前,生命周期扩展规则不能确保 get_vector 返回的容器在 lifetime_of_temp_not_extended 中被扩展。这是因为临时容器没有绑定到右值引用。

#include <vector>

std::vector<int> get_vector();

void use(int);

void lifetime_of_temp_extended() {
  for(auto x : get_vector()) {
    use(x); // GOOD: The lifetime of the vector returned by `get_vector()` is extended until the end of the loop.
  }
}

// Writes the the values of `v` to an external log and returns it unchanged.
const std::vector<int>& log_and_return_argument(const std::vector<int>& v);

void lifetime_of_temp_not_extended() {
  for(auto x : log_and_return_argument(get_vector())) {
    use(x); // BAD: The lifetime of the vector returned by `get_vector()` is not extended, and the behavior is undefined.
  }
}

要修复 lifetime_of_temp_not_extended,请考虑重写代码以扩展临时对象的生命周期。在 fixed_lifetime_of_temp_not_extended 中,临时对象的生命周期通过将其存储在右值引用中来扩展。

void fixed_lifetime_of_temp_not_extended() {
  auto&& v = get_vector();
  for(auto x : log_and_return_argument(v)) {
    use(x); // GOOD: The lifetime of the container returned by `get_vector()` has been extended to the lifetime of `v`.
  }
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私