MST

星途 面试题库

面试题:C语言字符串函数安全隐患及优化

在C语言中,像strcpy、strcat这类字符串函数存在一定安全隐患,请详细说明这些隐患是什么,如何利用这些隐患进行恶意攻击,以及如何使用更安全的替代函数(如strncpy、strncat等)来优化代码,同时举例说明优化前后代码的区别。
37.2万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

1. 隐患说明

  • 缓冲区溢出strcpy 函数将源字符串复制到目标字符串时,不会检查目标缓冲区的大小。如果源字符串长度超过目标缓冲区大小,就会导致缓冲区溢出,覆盖相邻内存区域的数据,可能破坏程序的正常运行,甚至导致程序崩溃。strcat 函数在拼接字符串时也存在同样问题,它不会考虑目标缓冲区剩余空间是否足够容纳源字符串。

2. 恶意攻击方式

  • 栈溢出攻击:攻击者可以精心构造一个超长的字符串作为源字符串,传递给 strcpystrcat 函数。当这些函数将超长字符串复制或拼接进目标缓冲区时,会覆盖栈上的返回地址等关键信息。攻击者可以将返回地址修改为恶意代码的地址,当函数返回时,程序就会跳转到恶意代码处执行,从而获取系统权限或进行其他恶意操作。

3. 安全替代函数及优化方法

  • strncpystrncpy 函数原型为 char *strncpy(char *dest, const char *src, size_t n);,它最多复制 n 个字符从源字符串 src 到目标字符串 dest。如果 src 的长度小于 n,则 dest 会以空字符填充直到长度为 n;如果 src 的长度大于或等于 n,则 dest 不会以空字符结尾,需要手动添加。
  • strncatstrncat 函数原型为 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;
}

在优化后的代码中,strncpystrncat 函数通过限制复制或拼接的字符数量,有效避免了缓冲区溢出问题。