ceacer 2 已发布 1月28号 分享 已发布 1月28号 在 C 语言编程中,我们常常会涉及到字符串操作,如文件读写、协议交互等等,此时我们可以使用 C 库中自带的字符串操作函数,由于库已经帮我们封装好了各种字符串操作的内部实现,用起来自然也是非常方便。然而,我们日常使用的库函数有一部分实际上是不安全的!稍不注意就会导致数据异常,甚至程序崩溃。下面我们就来列举几个常见的“不安全”函数,看看你中招了吗? gets – 从标准输入中读取一行字符串 gets 的函数声明如下: char *gets(char *str) 该函数会从标准输入读取一行,并将其存储在指定的缓冲区 str 中。读取操作在遇到换行符或文件结束符时终止,并用空字符(null)终止字符串。但该函数不会检查输入字符串的长度。一旦标准输入中的字符串长度大于 str 缓冲区的大小,此时就会导致缓冲区溢出,从而引发潜在的安全漏洞: char buffer[10]; gets(buffer); // 如果输入的字符串长度大于 10 就会导致缓冲区溢出 替代方案:fgets fgets 的函数声明如下: char *fgets(char *str, int n, FILE *stream) 该函数会从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止。由于限定了读取的最大长度(当然此处长度必须要合理,如果缓冲区本身只有 10 个字节,你却硬是传了 15 进去,那只能说是程序 BUG 了),因此就避免了产生缓冲区溢出的问题: char buffer[10]; fgets(buffer, sizeof(buffer), stdin); // 无论输入是多长,此处 fgets 最多只会读 9 个有效字符 strcpy – 字符串拷贝 strcpy 函数的声明如下: char *strcpy(char *dest, const char *src) 该函数将源字符串复制到目标缓冲区中,包括终止的空字符(null)。但其不会检查目标缓冲区的大小,因此一旦源字符串长度超过目标缓冲区大小,就会导致缓冲区溢出: char dest[10];char *src = “This is a long string”;strcpy(dest, src); // 可能导致缓冲区溢出 替代方案:strncpy strncpy 函数的声明如下: char *strncpy(char *dest, const char *src, size_t n) 该函数把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。因此由于限制了复制的长度,同样也就不会导致缓冲区溢出。 char dest[10]; char *src = "This is a long string"; strncpy(dest, src, sizeof(dest) - 1); // 安全复制 dest[sizeof(dest) - 1] = ''; // 确保终 strcat – 字符串拼接 strcat 函数的声明如下: char *strcat(char *dest, const char *src) 该函数把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。很显然如果 src + dest 的字符串长度大于 dest 缓冲区的大小,就会造成缓冲区溢出: char dest[20] = “Hello, “;char *src = “world!”;strcat(dest, src); // 缓冲区溢出 替代方案:strncat strncat 函数的声明如下: char *strncat(char *dest, const char *src, size_t n) 该函数把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。由于限制了最大长度,一旦长度太大,追加的字符串就会被截断,自然也就不会出现缓冲区溢出的问题: char dest[10] = "Hello, "; char *src = "world!"; strncat(dest, src, sizeof(dest) - strlen(dest) - 1); // 安全追加 sprintf – 格式化字符串输出 sprintf 函数的声明如下: int sprintf(char *str, const char *format, …) 该函数会按指定要求格式化一个字符串并将其存储在目标缓冲区中。其不检查目标缓冲区的长度,因此当格式化出来的字符串长度大于目标缓冲区长度时,就会导致缓冲区溢出: char buffer[10];int value = 123;sprintf(buffer, “The value is %d”, value); // 缓冲区溢出 替代方案:snprintf snprintf 函数的声明如下: int snprintf ( char * str, size_t size, const char * format, … ) 该函数在 sprintf 函数的基础上增加了输出字符数的限制参数,从而避免缓冲区溢出。 char buffer[10];int value = 123;snprintf(buffer, sizeof(buffer), “The value is %d”, value); // 安全格式化 以上就是常用的几个 “不安全” 函数,你中招了吗?如果有类似的经历可以在评论区分享。 实际在实现对应功能时还是推荐要用这些函数的安全版本,如果出于某些原因不得不用这些函数,也一定要做好输入输出的限制,尽可能杜绝潜在的风险 。 评论链接 在其他网站上分享 更多分享选项...
推荐帖
创建账户或登录以发表评论
您需要成为会员才能发表评论
创建一个帐户
在我们的社区注册一个新账户。很简单!
注册新账户登入
已有账户?在此登录
立即登录