观察以下函数:
- void func(char *s1, char *s2) {
- char d[32];
- strncpy(d,s1,sizeof d - 1);
- strncat(d,s2,sizeof d - 1);
- ...
- }
答案:我们认为应该先来讲一讲虽然古老但却非常便于理解的缓冲区溢出。对许多人而言此代码已足够安全,因为代码使用的是受限的 strncpy 和 strncat 函数。但是,只有当缓冲区大小合适时,这些函数才是安全的,而在本例中缓冲区大小是错误的。彻头彻尾的错误。
从技术上讲,第一个调用是安全的,但第二个调用却是错误的。strncpy 和 strncat 函数的最后一个参数是缓冲区中保留的空间量,而您刚刚通过调用 strncpy 占用了其中的一部分或全部空间。缓冲区溢出。Michael 在 2004 年发表了一篇博客文章,其中讲述了与此完全相同的错误类型。
在 Visual C++ 2005 及以后的版本中,警告 C4996 是告诉您应将错误的函数调用替换为更安全的调用,而 /analyze 选项会发出 C6053 警告,指出 strncat 可能不会以零终止字符串
。
老实说,由于种种原因,strncpy 和 strncat(及其 "n" 同类)要比 strcpy 和 strcat(及其同类)更糟糕。首先,返回值有点多余 — 它是指向缓冲区的指针,而缓冲区可能有效,也可能无效。您没有办法知道!其次,获取正确的目标缓冲区大小的确很难。