写出完美的snprintf
平时公司的代码安全扫描会给出不安全代码的告警,其中会检查代码中间的strcpy和sprintf函数,而要求使用strncpy和snprintf。今天我们讨论一下怎样写出完美的snprintf。
snprintf是一个在C99才被加入如标准的函数,原来的各个编译器都有自己的实现,至少.NET2003编译器还要是使用_snprintf这样的函数名称。
而这些编译器间都有差异,而且Glibc库又有自己的不同的实现。
查询一下snprintf的函数的MSDN说明。如下:
Let len be the length of the formatted data string (not including the terminating null). len and count are in bytes for _snprintf, wide characters for _snwprintf.
If len < count, then len characters are stored in buffer, a null-terminator is appended, and len is returned.
If len = count, then len characters are stored in buffer, no null-terminator is appended, and len is returned.
If len > count, then count characters are stored in buffer, no null-terminator is appended, and a negative value is returned.
If buffer is a null pointer and count is nonzero, or format is a null pointer, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, these functions return -1 and set errno to EINVAL.
For information about these and other error codes, see _doserrno, errno, _sys_errlist, and _sys_nerr.
当buffer长度不够时,返回的是负数。
而LINUX的说明如下:
Return value
Upon successful return, these functions return the number of characters printed (not
including the trailing '\0' used to end output to strings). The functions snprintf() and
vsnprintf() do not write more than size bytes (including the trailing '\0'). If the out-
put was truncated due to this limit then the return value is the number of characters (not
including the trailing '\0') which would have been written to the final string if enough
space had been available. Thus, a return value of size or more means that the output was
truncated. (See also below under NOTES.) If an output error is encountered, a negative
value is returned.
NOTES
The glibc implementation of the functions snprintf() and vsnprintf() conforms to the C99
standard, i.e., behaves as described above, since glibc version 2.1. Until glibc 2.0.6
they would return -1 when the output was truncated.
在比较新的版本中,其遵守C99的规范,当buffer长度不够时,返回的是超过Buffer长度的正数。
你会发现,如果传递的buf的长度不够的情况下,null-terminator都没有加入。。。。。那么你使用的时候还是可能溢出。而且返回值的判断在不同的平台还可能不一样。
当然我理解使用snprintf的主要好处在于安全性,但是如果使用不对仍然可能有悲剧发生,比如你的更新SQL语句被截断了WHERE条件。所以返回值还是要判断。
那么最简单的方法还是传递的给snprintf的长度参数count应该buf长度-1,然后还要将最后一个字符改为null-terminator。然后再加入相应的判断。
发现返回值小于0或者大于(可能有等于,看你传递的长度参数和Buffer的关系)实际长度时认为出现问题。
经过测试的正确写法:
max_len = sizeof(buf)-1;
len = snprintf(buf, max_len, ...);
if ((len < 0) || (len > max_len))
{
//错误处理
}
else
{
buf[max_len]=0;
do job...
}
代码说明:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h> int main(int argc, char** argv)
{
if (argc < )
{
printf("usage:./snprintf_perfect xxxx\n");
return -;
}
char buffer[];
size_t max_len = sizeof(buffer) - ;
int len = snprintf(buffer, max_len, "%s", argv[]);
if ((len < ) || (len > max_len))
{
printf("overflow!!\n");
}
else
{
buffer[max_len] = ;
printf("%s\n", buffer);
} return ;
}
结果说明:
# 长度为buffer长度-1
[root@rocket linux_programming]# ./snprintf_perfect 012345678901234
01234567890123
# 长度为buffer长度,溢出!
[root@rocket linux_programming]# ./snprintf_perfect 0123456789012345
overflow!!
写出完美的snprintf的更多相关文章
- 在java中写出完美的单例模式
1. 前言 单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java开发者,也许你觉得自己对单例 ...
- 写出完美论文的十个技巧10 Tips for Writing the Perfect Paper
10 Tips for Writing the Perfect Paper Like a gourmet meal or an old master painting, the perfect col ...
- 写出优美代码的两个方式:一步到位VS迭代优化
最近把手头这个安卓APP的所有事务性方法都写完了,有了以下体会,新手体会,老鸟轻拍 想写成优美代码的人一般都会有这样的想法: 一定要在写每一句代码,写每一个方法,构造每一个类的时候,都要记得优化: ...
- 如何写出如散文般的代码――《代码整洁之道》读书笔记(Ch1-Ch3)
不知道有多少人像我一样,程序出现问题时添加函数添加变量解决,变量名用a,b,c等"简单"的字母来表示.不知道有多少人像我一样,看完自己的代码,心里暗骂"什么玩意儿!&qu ...
- 让你用sublime写出最完美的python代码--windows环境
至少很长一段时间内,我个人用的一直是pycharm,也感觉挺好用的,也没啥大毛病 但是pycharm确实有点笨重,啥功能都有,但是有很多可能这辈子我也不会用到,并且pycharm打开的速度确实不敢恭维 ...
- (转)Python新手写出漂亮的爬虫代码1——从html获取信息
https://blog.csdn.net/weixin_36604953/article/details/78156605 Python新手写出漂亮的爬虫代码1初到大数据学习圈子的同学可能对爬虫都有 ...
- 我的Java历程_写出这个数
lzJava基础进行中,今天偶然间看到的一个题目: 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字.如下代码: import java.util.*;public class Ma ...
- 前端一面/面试常考题1-页面布局:假设高度已知,请写出三栏布局,其中左栏、右栏宽度各为300px,中间自适应。
题目:假设高度已知,请写出三栏布局,其中左栏.右栏宽度各为300px,中间自适应. [题外话:日常宣读我的目标===想要成为一名优雅的程序媛] 一.分析 1. 题目真的像我们想得这么简单吗? 其实不然 ...
- 如何写出同事看不懂的Java代码?
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是没更新就是在家忙着带娃的Hydra. 前几天,正巧赶上组里代码review,一下午下来,感觉整个人都血压拉满了.五花八门的代码 ...
随机推荐
- 针对访问uri 限制ip
在虚拟主机配置文件中加入如下字段: <filesmatch "(.*)admin(.*)"> Order deny,allow ...
- #define,#undef宏学习
1.预处理器 1.1预处理符号: __FILE__ :进行编译的源文件名字 __LINE__ :文件当前行的行号 __DATA__ :文件被编译的日期 __TIME__ :文件被编译的时间 __STD ...
- SWIG 多语言接口变换 【转】
一. SWIG 是Simple Wrapper and Interface Generator的缩写,是一个帮助使用C或者C++编写的软件创建其他编语言的API的工具.例如,我 ...
- awk使用记录
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...
- Microsoft Sync Framework 2.1 可再发行程序包 Microsoft Sync Framework 1.0 SP1 - 中文(简体)
Sync Framework 2.1 引入了新功能,这些功能支持您计算机上的 SQL Server 或 SQL Server Compact 数据库与 SQL Azure 数据库进行同步.此发行版还引 ...
- 使用WIFI连接android进行调试和adb操作
本人需要wifi连接android进行调试的原因主要是要经常用到IDA pro进行调试,但手头有的IDA Pro版本只是windows的,开发可能更多用Mac OS X了,来回拔插.调试很不方便,所以 ...
- hbuilder - wap to app
官方文档: http://www.dcloud.io/wap2app.html 新建Wap2App,示例网址:www.baidu.com 随后,我们可以在 最后,我们可以 打包完成以后,下载即可
- HTTP常用的请求头和响应头
1.请求头 Connection:表示是否需要持久连接.若值为Keep-Alive,就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间.要实现这一点, ...
- HDU1789 Doing Homework again 【贪心】
Doing Homework again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- 【Excle数据透视表】如何按照地区交替填充背景颜色
现存在如下数据透视表 需要根据地区填充不同的背景颜色 步骤 选定数值区域→开始→条件格式→新建规则,出现如下窗口: 公式:=MOD(COUNT(1/(MATCH($A$4:$A4,$A$4:$A4,) ...