STR50-CPP. 确保有足够的空间来存储字符串的字符数据和空终终止符
原文链接:
将数据拷贝到不够大的缓存中会导致缓冲区溢出 (buffer overflow). 缓冲区移除经常发生在字符串操作上 [Seacord 2013]. 为避免这类错误, 无论时通过截断限制拷贝, 或者, 最好是确保目标地址能有足够大小来保存被拷贝的数据. C 风格的字符串需要一个空字符来标识字符串的结尾, 但是 C++ std::basic_string
模板不需要该空字符.
不合规代码示例
因为输入是无界的, 所以下述代码可能导致缓冲区溢出.
1 |
|
不合规代码示例
为解决这个问题, 可能会使用 std::ios_base::width()
方法, 但是仍然是个陷阱, 如下不合规代码示例所示.
1 |
|
在这个例子中, 第一次读取不会溢出, 但是填充 bufOne
字符串会被截断. 进而, 第二次读取时仍然溢出 bufTwo
. C++ Standard, [istream.extractors], paragraphs 7–9 [ISO/IEC 14882-2014], 表述了 operator>>(basic_istream &, charT *)
的行为, 部分表述如下:
operator>>
会在下个位置存储一个空字节 (charT()
) – 如果没有字符输入, 这可能是第一个位置.operator>>
继而调用width(0)
.
operator>>
then stores a null byte (charT()
) in the next position, which may be the first position if no characters were extracted.operator>>
then callswidth(0)
.
因此, 在每次调用 operator>>
输入有界数组前优先调用 width()
是必要的. 然而, 这并没有解决输入被切断的问题 – 可能导致信息丢失或者潜在 漏洞, vulnerability.
合规示例
确保数据不被截断并避免缓冲区溢出的最佳方案是用 std::string
来代替有界数组, 类似这个合规方案.
1 |
|
不合规代码示例
在这个不合规代码示例中, 使用未格式化的输入函数从给定文件中读取一个包含 32 个字符的未格式化的字符数组. 然而, read()
函数未保证该字符串以 null 结尾, 所以如果该字符数组不包含一个空终止符, 后续 std::string
构造函数的调用导致 未定义行为, undefined behavior .
1 |
|
合规方案
这个合规方案假设从文件输入最多 32 个字符. 该方案基于从输入流读取的字符数量构造了一个 std::string
对象, 而不是插入一个空终止符. 如果输入的大小是不确定的, 最好根据实际需求使用 std::basic_istream<T>::readsome()
或者格式化输入函数.
1 |
|
Risk Assessment
Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code with the permissions of the vulnerable process.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
STR50-CPP | High | Likely | Medium | P18 | L1 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
CodeSonar | 6.1p0 | *MISC.MEM.NTERM***LANG.MEM.BO LANG.MEM.TO ** | No space for null terminatorBuffer overrun Type overrun |
Helix QAC | 2021.2 | C++2835, C++2836, C++2839, C++5216 | |
Klocwork | 2021.1 | NNTS.MIGHT NNTS.TAINTED | |
LDRA tool suite | 9.7.1 | 489 S, 66 X, 70 X, 71 X** ** | Partially implemented |
Parasoft C/C++test | 2021.1 | CERT_CPP-STR50-b CERT_CPP-STR50-c CERT_CPP-STR50-e CERT_CPP-STR50-f CERT_CPP-STR50-g | Avoid overflow due to reading a not zero terminated string Avoid overflow when writing to a buffer Prevent buffer overflows from tainted data Avoid buffer write overflow from tainted data Do not use the ‘char’ buffer to store input from ‘std::cin’ |
Polyspace Bug Finder | R2021b | CERT C++: STR50-CPP | Checks for:Use of dangerous standard functionMissing null in string arrayBuffer overflow from incorrect string format specifierDestination buffer overflow in string manipulationRule partially covered. |
SonarQube C/C++ Plugin | 4.10 | S3519 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C Coding Standard | STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator |
---|---|
Bibliography
[ISO/IEC 14882-2014] | Subclause 27.7.2.2.3, “basic_istream::operator>> “ Subclause 27.7.2.3, “Unformatted Input Functions” |
---|---|
[Seacord 2013] | Chapter 2, “Strings” |
本文标题:STR50-CPP. 确保有足够的空间来存储字符串的字符数据和空终终止符
文章作者:xwnb
发布时间:2021-11-20
最后更新:2023-04-17
原始链接:https://xwnb.github.io/posts/2736214874/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!并保留本声明。感谢您的阅读和支持!
分享