strcpy() 是 C 标准库函数,用于字符串拷贝,但它 不检查目标缓冲区大小 ,容易导致缓冲区溢出。
1 函数原型
cpp
char* strcpy(char* dest, const char* src);
将 src 指向的字符串(包括结尾的 \0 )拷贝到 dest 指向的缓冲区,返回 dest 。
1.1 边界值问题
1.1.1 目标缓冲区必须足够大
strcpy 不检查 dest 的大小,如果 src 长度 ≥ dest 缓冲区大小,会发生 缓冲区溢出 ,导致未定义行为(崩溃、数据损坏、安全漏洞)。
溢出案例, 如下:
cpp
// 错误示例:缓冲区只有 5 字节,"hello world" 有 12 字节(含 \0)
char buf[5];
strcpy(buf, "hello world"); // 溢出!
1.1.2 源字符串必须以 \0 结尾
如果 src 不是合法的 C 字符串(缺少 \0 ), strcpy 会一直读到内存中遇到 \0 为止,同样导致溢出。
溢出案例, 如下:
cpp
// 错误示例:没有 \0 终止符
char src[] = {'a', 'b', 'c'}; // 不是字符串
char buf[10];
strcpy(buf, src); // 未定义行为
1.3 内存不能重叠
如果 dest 和 src 指向同一块内存且有重叠,结果未定义。重叠拷贝应使用 memmove 。
2 修复方法
2.1 使用 snprintf()
snprintf()函数,在字符串拷贝时,会自动补上\0
cpp
char buf[5];
snprintf(buf, sizeof(buf), "%s", "hello world");
// 结果:buf = "hell",自动以 \0 结尾
2.2 使用string替代char*
cpp
std::string src = "hello world";
std::string dest = src; // 自动管理内存,无溢出风险