面试题答案
一键面试1. 隐患说明
- 缓冲区溢出:
strcpy
函数将源字符串复制到目标字符串时,不会检查目标缓冲区的大小。如果源字符串长度超过目标缓冲区大小,就会导致缓冲区溢出,覆盖相邻内存区域的数据,可能破坏程序的正常运行,甚至导致程序崩溃。strcat
函数在拼接字符串时也存在同样问题,它不会考虑目标缓冲区剩余空间是否足够容纳源字符串。
2. 恶意攻击方式
- 栈溢出攻击:攻击者可以精心构造一个超长的字符串作为源字符串,传递给
strcpy
或strcat
函数。当这些函数将超长字符串复制或拼接进目标缓冲区时,会覆盖栈上的返回地址等关键信息。攻击者可以将返回地址修改为恶意代码的地址,当函数返回时,程序就会跳转到恶意代码处执行,从而获取系统权限或进行其他恶意操作。
3. 安全替代函数及优化方法
strncpy
:strncpy
函数原型为char *strncpy(char *dest, const char *src, size_t n);
,它最多复制n
个字符从源字符串src
到目标字符串dest
。如果src
的长度小于n
,则dest
会以空字符填充直到长度为n
;如果src
的长度大于或等于n
,则dest
不会以空字符结尾,需要手动添加。strncat
:strncat
函数原型为char *strncat(char *dest, const char *src, size_t n);
,它将源字符串src
最多n
个字符追加到目标字符串dest
的末尾。dest
必须以空字符结尾,并且dest
要有足够的空间来容纳追加后的字符串(包括空字符)。
4. 代码示例
优化前(存在隐患)
#include <stdio.h>
#include <string.h>
int main() {
char dest[10];
char src[] = "Hello, World!";
strcpy(dest, src); // 这里会导致缓冲区溢出,因为src长度超过dest大小
printf("%s\n", dest);
return 0;
}
优化后(使用安全函数)
#include <stdio.h>
#include <string.h>
int main() {
char dest[10];
char src[] = "Hello, World!";
strncpy(dest, src, sizeof(dest) - 1); // 最多复制dest大小 - 1 个字符,防止溢出
dest[sizeof(dest) - 1] = '\0'; // 手动添加空字符
printf("%s\n", dest);
char dest2[20] = "Hello, ";
strncat(dest2, src, sizeof(dest2) - strlen(dest2) - 1); // 防止拼接时溢出
printf("%s\n", dest2);
return 0;
}
在优化后的代码中,strncpy
和 strncat
函数通过限制复制或拼接的字符数量,有效避免了缓冲区溢出问题。