老话题,但我也遇到过这个问题。AIX 6.1 上的一个简单测试程序与 AIX 的 MALLOCDEBUG 一起确认了该问题。
#include <string.h>
int main(void)
{
char test[32] = "1234";
char *newbuf = NULL;
newbuf = strndup(test, sizeof(test)-1);
}
编译并运行带有缓冲区溢出检测的程序:
~$ gcc -g test_strndup2.c
~$ MALLOCDEBUG=catch_overflow ./a.out
Segmentation fault (core dumped)
现在运行 dbx 来分析内核:
~$ dbx ./a.out /var/Corefiles/core.6225952.22190412
Type 'help' for help.
[using memory image in /var/Corefiles/core.6225952.22190412]
reading symbolic information ...
Segmentation fault in strncpy at 0xd0139efc
0xd0139efc (strncpy+0xdc) 9cc50001 stbu r6,0x1(r5)
(dbx) where
strncpy() at 0xd0139efc
strndup@AF5_3(??, ??) at 0xd03f3f34
main(), line 8 in "test_strndup2.c"
跟踪 strndup 中的指令,它似乎分配了一个缓冲区,该缓冲区刚好足以处理 s 中的字符串加上一个 NULL 终止符。但是,它总是将 n 个字符复制到新缓冲区,必要时用零填充,如果 strlen(s) < n 会导致缓冲区溢出。
char* strndup(const char*s, size_t n)
{
char* newbuf = (char*)malloc(strnlen(s, n) + 1);
strncpy(newbuf, s, n-1);
return newbuf;
}