请选择 进入手机版 | 继续访问电脑版

专注代码检测 - 阅镜

 找回密码
 立即注册
热搜: 安装 代码
查看: 73|回复: 0

不得直接使用无长度限制的字符拷贝函数

[复制链接]

70

主题

70

帖子

230

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
230
发表于 2021-9-10 14:41:05 | 显示全部楼层 |阅读模式
不应直接使用legacy的字符串拷贝、输入函数,如strcpy、strcat、sprintf、wcscpy、mbscpy等,这些函数的特征是:可以输出一长串字符串,而不限制长度。如果环境允许,应当使用其_s安全版本替代,或者使用n版本函数(如:snprintf,vsnprintf)。

若使用形如sscanf之类的函数时,在处理字符串输入时应当通过%10s这样的方式来严格限制字符串长度,同时确保字符串末尾有\0。如果环境允许,应当使用_s安全版本。

但是注意,虽然MSVC 2015时默认引入结尾为0版本的  snprintf (行为等同于C99定义的  snprintf )。但更早期的版本中,MSVC的  snprintf 可能是  _snprintf 的宏。而  _snprintf 是不保证\0结尾的。

因此,在使用n系列拷贝函数时,要确保正确计算缓冲区长度,同时,如果你不确定是否代码在各个编译器下都能确保末尾有0时,建议可以适当增加1字节输入缓冲区,并将其置为\0,以保证输出的字符串结尾一定有\0。
  1. // Good
  2. char buf[101] = {0};
  3. snprintf(buf, sizeof(buf) - 1, "foobar ...", ...);
复制代码
一些需要注意的函数,例如  strncpy 和  _snprintf 是不安全的。  strncpy 不应当被视为  strcpy 的n系列函数,它只是恰巧与其他n系列函数名字很像而已。 strncpy 在复制时,如果复制的长度超过n,不会在结尾补\0。
同样,MSVC  _snprintf 系列函数在超过或等于n时也不会以0结尾。如果后续使用非0结尾的字符串,可能泄露相邻的内容或者导致程序崩溃
  1. // Bad
  2. char a[4] = {0};
  3. _snprintf(a, 4, "%s", "AAAA");
  4. foo = strlen(a);
复制代码
上述代码在MSVC中执行后, a[4] == 'A',因此字符串未以0结尾。a的内容是"AAAA",调用  strlen(a) 则会越界访问。因此,正确的操作举例如下:

  1. // Good
  2. char a[4] = {0};
  3. _snprintf(a, sizeof(a), "%s", "AAAA");
  4. a[sizeof(a) - 1] = '\0';
  5. foo = strlen(a);
复制代码
在 C++ 中,强烈建议用  string 、 vector  等更高封装层次的基础组件代替原始指针和动态数组,对提高代码的可读性和安全性都有很大的帮助。

可能产生的漏洞:
  1.   中风险-信息泄露

  2.   低风险-拒绝服务

  3.   高风险-缓冲区溢出
复制代码
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

QQ|Archiver|手机版|小黑屋| 阅镜 ( 京ICP备2020034574号 )|网站地图|网站地图点击这里给我发消息

GMT+8, 2021-10-27 03:02 , Processed in 0.993397 second(s), 29 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表