写出完美的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,一下午下来,感觉整个人都血压拉满了.五花八门的代码 ...
随机推荐
- yaffs和jffs2简单比较
转:http://blog.chinaunix.net/uid-27675161-id-3392636.html 相关知识引用<嵌入式 Linux 应用开发 完全手册> Nand F ...
- JAVA实现网页快照,存为图片格式
原文:http://blog.csdn.net/java2000_net/article/details/3643528 截取的google的效果,将就吧,不是特别好. 但是作为普通的应用,我想这个效 ...
- 基于Prometheus,Alermanager实现Kubernetes自动伸缩
到目前为止Kubernetes对基于cpu使用率的水平pod自动伸缩支持比较良好,但根据自定义metrics的HPA支持并不完善,并且使用起来也不方便. 下面介绍一个基于Prometheus和Aler ...
- Android API level 与version对应关系
https://www.cnblogs.com/jinglecode/p/7753107.html Platform Version API Level VERSION_CODE 中文名称 Andro ...
- ubuntu live cd修复grub引导项
1. 通过Ubuntu Live CD(安装盘,选择try Ubuntu)进入Ubuntu系统 打开终端,依次进行如下操作: 1. sudo fdisk -l 出现如下界面: 2. 然后会看到,有好多 ...
- Linux学习之二十一-shell编程基础
Shell编程基础 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个 ...
- 用Jmeter对数据库执行压力测试
转载:http://www.cnblogs.com/chengtch/p/6198900.html 在我看来压力测试的压测对象可以分为UI,接口及数据库三个部分吧,对界面及接口进行压测还算熟悉, 定位 ...
- jdk/java版本与Android源码编译中的错误
错误一:javap未指向有效的java版本 Traceback (most recent call last): File "../../base/android/jni_generator ...
- Win7如何安装IIS来浏览ASP网站
1 进入控制面板-->程序与功能-->点击左侧的"打开或关闭Windows功能"-->把"Internet信息服务"给勾上,点击"确 ...
- vscode - 更改emmet生成代码
有时候生成的代码,并不适用自己,所以想想改生成代码: 因为windows查找文件/文件内容非常慢,所以借用了一下Linux的搜索命令,查找了一下 ie=edge ,最后,找到了 expand-ful ...