Bál*_*ász 4 c c++ string recursion strlen
我想出了这个小代码,但所有专业人士都表示它很危险,我不应该写这样的代码.任何人都可以在"更多"细节中突出其漏洞吗?
int strlen(char *s){
return (*s) ? 1 + strlen(s + 1) : 0;
}
Run Code Online (Sandbox Code Playgroud)
它本身没有漏洞,这是完全正确的代码.当然,这是过早的悲观.除了最短的字符串之外,它将耗尽堆栈空间,并且由于递归调用,它的性能会很糟糕,但是否则就可以了.
尾调用优化很可能无法处理这样的代码.如果你想危险地生活并依赖尾调优化,你应该改为使用尾调用:
// note: size_t is an unsigned integertype
int strlen_impl(const char *s, size_t len) {
if (*s == 0) return len;
if (len + 1 < len) return len; // protect from overflows
return strlen_impl(s+1, len+1);
}
int strlen(const char *s) {
return strlen_impl(s, 0);
}
Run Code Online (Sandbox Code Playgroud)
此代码中存在两个严重的安全漏洞:
使用int而不是size_t返回类型.如上所述,字符串长于INT_MAX将导致此函数通过整数溢出调用未定义的行为.在实践中,这可能导致计算strlen(huge_string)为一些小的值,如1,malloc"错误的内存量,然后执行strcpy它,导致缓冲区溢出.
无限递归,可以溢出堆栈,即堆栈溢出.:-)编译器可以选择优化递归到循环(在这种情况下,它可以使用当前的编译器技术),但不能保证它会.在最好的情况下,堆栈溢出只会使程序崩溃.在最坏的情况下(例如,在没有保护页面的线程上运行),它可能会破坏不相关的内存,可能会产生任意代码执行.