从流中读取:
根据GNU C编程教程中的getline:
getline函数将通过realloc函数自动扩大内存块,因此永远不会出现空间短缺的情况,这也是getline如此安全的原因之一。[...]请注意,无论输入有多长,getline都可以安全地处理您的输入行。
我认为,在读取流时,getline应该在所有输入下都能防止缓冲区溢出发生。
- 我的假设正确吗?在输入和/或分配方案下,这是否会导致漏洞?例如,如果流的第一个字符是一些奇异的控制字符,比如0x08 BACKSPACE(ctl-H)。
- 是否有任何工作可以数学证明getline是安全的?
malloc在失败时返回空指针:
如果malloc遇到错误,则malloc返回空指针。这会带来安全风险,因为人们仍然可以将指针算术应用于空(0x0)指针,因此维基百科建议。
/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
/* Memory could not be allocated, the program should handle
the error here as appropriate. */
}
安全的sscanf:
在使用sscanf时,我习惯于将要提取的字符串分配为输入字符串的大小,以避免可能发生的溢出。例如:
const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];
sscanf(inputStr, formatStr, str1, str2);
因为str1和str2的大小与inputStr相同,而且从inputStr中读取的字符数不超过strlen(inputStr),所以似乎不可能在给定inputStr的所有可能值的情况下导致缓冲区溢出?
- 我说得对吗?有我没有考虑到的奇怪情况吗?
- 有更好的编写方式吗?已经解决了这个问题的库?
一般问题:
虽然我发布了大量问题,但我并不希望任何人回答所有问题。这些问题更多是指导我寻找答案类型的线索。我真的想学习安全的C语言思维方式。
- 还有哪些安全的C语言惯用法?
- 我需要始终检查哪些边角情况?
- 如何编写单元测试来执行这些规则?
- 如何以可测试或可证明正确的方式强制执行约束条件?
- 有哪些推荐的C语言静态/动态分析技术或工具?
- 您遵循哪些安全的C语言实践,以及如何向自己和他人证明它们的合理性?
资源:
许多资源都是从答案中借用的。
- David Wheeler的Linux和Unix安全编程HOWTO
- SUN Microsystems的安全C编程
- 通过示例学习不安全的编程
- Add More NOPS - 博客介绍这些问题
- CERT安全编码计划
- flawfinder - 静态分析工具
- 使用Thm Provers证明安全性 by Yannick Moy
- libsafe
strlen()
,应该将其存储在变量中:size_t len = strlen(inputStr); char *str1[len]; char *str2[len];
编译器可能会自动为您完成此操作,但自己手动完成并不难,而且代码可读性更高,确保得到的结果也是你想要的。 - Chris Lutz