CodeQL 文档

生命周期结束后使用字符串

ID: cpp/use-of-string-after-lifetime-ends
Kind: problem
Security severity: 8.8
Severity: warning
Precision: high
Tags:
   - reliability
   - security
   - external/cwe/cwe-416
   - external/cwe/cwe-664
Query suites:
   - cpp-code-scanning.qls
   - cpp-security-extended.qls
   - cpp-security-and-quality.qls

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

std::string 对象上调用 c_str 会返回一个指向底层字符数组的指针。当 std::string 对象被销毁时,c_str 返回的指针将不再有效。如果在 std::string 对象被销毁后使用该指针,则行为未定义。

通常,当函数调用(或重载运算符)按值返回 std::string 并且结果没有立即以值或引用的方式存储在变量中以延长临时对象的生命周期时,就会出现此问题。生成的临时 std::string 对象会在包含表达式语句的末尾被销毁,同时还会销毁通过调用 c_str 返回的任何内存。

建议

确保 c_str 返回的指针不会比底层 std::string 对象的生存期长。

示例

以下示例连接了两个 std::string 对象,然后使用 c_str 将生成的字符串转换为 C 字符串,以便将其传递给 work 函数。但是,表示连接字符串的底层 std::string 对象会在调用 c_str 返回后立即被销毁。这意味着 work 会收到一个指向无效内存的指针。

#include <string>
void work(const char*);

// BAD: the concatenated string is deallocated when `c_str` returns. So `work`
// is given a pointer to invalid memory.
void work_with_combined_string_bad(std::string s1, std::string s2) {
  const char* combined_string = (s1 + s2).c_str();
  work(combined_string);
}

以下示例通过确保调用 c_str 返回的指针不会比底层 std::string 对象的生存期长来修复上述代码。这确保了传递给 work 的指针指向有效的内存。

#include <string>
void work(const char*);

// GOOD: the concatenated string outlives the call to `work`. So the pointer
// obtainted from `c_str` is valid.
void work_with_combined_string_good(std::string s1, std::string s2) {
  auto combined_string = s1 + s2;
  work(combined_string.c_str());
}

参考资料

  • ©GitHub公司
  • 条款
  • 隐私