用 snprintf / asprintf 取代不安全的 sprintf
2015-07-18 16:37
726 查看
snprintf (或者_snprintf )可以用来只计算长度,如:int c = snprintf(NULL,0,......);
asprintf
第一个参数是指向指针的指针,它会在heap中自动申请空间(最后要手动free)。使用asprintf
,要加上 #define _GNU_SOURCE
在 C语言里,要建立一个字符数组的字符串,常常会使用
sprintf()
这个函数来做格式化的处理。但是实际上,这个函式却不是那么「安全」。怎么说呢?sprintf()
的整个界面长的样子的是:
int sprintf ( char * str, const char * format, ...)
函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。
函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。
也就是在使用前,必须要先建立好一个字符数组的空间,再用这个函式把内容填入,下面就是简单的例子:
int tmp = 10;
char cstr[20];
sprintf( cstr, "%d * %d = %d", tmp, tmp, tmp * tmp );
在 这个例子里,cstr最后的值,会是「10 * 10 =100」,看起来好像很好?但是如果把 tmp 的值改成 10000 的话,cstr 则应该要变成「10000 * 10000 = 100000000」,但是由于这时候的字符串所需长度为26,而要写入的 cstr 的长度只有20,所以就会造成 buffer overflow 的问题。
像如果是以 Visual C++ 2006来编译的话,如果程序里有用到 sprintf(),他在编译时就会显示一个警告讯息:
warning C4996: 'sprintf': This function orvariable may be unsafe. Consider using sprintf_sinstead.
而要怎么避免 sprintf 的buffer overflow的问题呢?除了微软建议的 sprintf_s() 外,实际上在 C99 里, 也多了一个
snprinf() 是用来取代现有的sprintf()了~他的界面是:
int snprintf(char *str, size_t size, const char *restrict format, ...)
应该可以明显看得出来,snprinf() 这个函式比 sprintf() 多了一个参数
size;这个参数的用处,就是用来限制最大的写入数据量,可以用来避免bufferoverflow。以上面的例子来说,本来写:
int tmp = 10000;
char cstr[20];
sprintf( cstr, "%d * %d = %d", tmp, tmp, tmp * tmp );
的话,会产生 buffer overflow的问题。而如果改成用 snprinf() 的话,就是变成:
int tmp = 10000;
char cstr[20];
snprintf( cstr, sizeof( cstr ), "%d * %d = %d", tmp,tmp, tmp * tmp );
这样一来,snprinf()在把数据写到 cstr时,最多就只会写入20个字符(cstr的长度),而不会有 bufferoverflow 的问题了~
int asprintf(char **strp, const char *fmt,
...);
int vasprintf(char **strp, const char *fmt,
va_list ap);
描述
函数 asprintf()和 vasprintf()是 sprintf(3)和 vsprintf(3)的对等物,除了它们分配一个包括结尾空字符在内的足够大的输出内存,并且通过其第一个参数返回。这个指针应该传给 free(3)以在不再使用时释放它。
返回值
当成功时,如同 sprintf(3)一样,这些函数返回打印的字节个数。如果内存分配失败,或者其它错误发生了,这些函数返回
-1,并且 strp 的内容是未定义的。
asprintf
第一个参数是指向指针的指针,它会在heap中自动申请空间(最后要手动free)。使用asprintf
,要加上 #define _GNU_SOURCE
在 C语言里,要建立一个字符数组的字符串,常常会使用
sprintf()
这个函数来做格式化的处理。但是实际上,这个函式却不是那么「安全」。怎么说呢?sprintf()
的整个界面长的样子的是:
int sprintf ( char * str, const char * format, ...)
函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。
函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。
也就是在使用前,必须要先建立好一个字符数组的空间,再用这个函式把内容填入,下面就是简单的例子:
int tmp = 10;
char cstr[20];
sprintf( cstr, "%d * %d = %d", tmp, tmp, tmp * tmp );
在 这个例子里,cstr最后的值,会是「10 * 10 =100」,看起来好像很好?但是如果把 tmp 的值改成 10000 的话,cstr 则应该要变成「10000 * 10000 = 100000000」,但是由于这时候的字符串所需长度为26,而要写入的 cstr 的长度只有20,所以就会造成 buffer overflow 的问题。
像如果是以 Visual C++ 2006来编译的话,如果程序里有用到 sprintf(),他在编译时就会显示一个警告讯息:
warning C4996: 'sprintf': This function orvariable may be unsafe. Consider using sprintf_sinstead.
而要怎么避免 sprintf 的buffer overflow的问题呢?除了微软建议的 sprintf_s() 外,实际上在 C99 里, 也多了一个
snprinf() 是用来取代现有的sprintf()了~他的界面是:
int snprintf(char *str, size_t size, const char *restrict format, ...)
应该可以明显看得出来,snprinf() 这个函式比 sprintf() 多了一个参数
size;这个参数的用处,就是用来限制最大的写入数据量,可以用来避免bufferoverflow。以上面的例子来说,本来写:
int tmp = 10000;
char cstr[20];
sprintf( cstr, "%d * %d = %d", tmp, tmp, tmp * tmp );
的话,会产生 buffer overflow的问题。而如果改成用 snprinf() 的话,就是变成:
int tmp = 10000;
char cstr[20];
snprintf( cstr, sizeof( cstr ), "%d * %d = %d", tmp,tmp, tmp * tmp );
这样一来,snprinf()在把数据写到 cstr时,最多就只会写入20个字符(cstr的长度),而不会有 bufferoverflow 的问题了~
int asprintf(char **strp, const char *fmt,
...);
int vasprintf(char **strp, const char *fmt,
va_list ap);
描述
函数 asprintf()和 vasprintf()是 sprintf(3)和 vsprintf(3)的对等物,除了它们分配一个包括结尾空字符在内的足够大的输出内存,并且通过其第一个参数返回。这个指针应该传给 free(3)以在不再使用时释放它。
返回值
当成功时,如同 sprintf(3)一样,这些函数返回打印的字节个数。如果内存分配失败,或者其它错误发生了,这些函数返回
-1,并且 strp 的内容是未定义的。
相关文章推荐
- C#、ASP.NET、WinForm - 实现邮件发送的功能
- ASP.NET中将声音文件添加到资源中并进行播放的方法
- ASP.NET的Page_Load事件
- B/S在北大青鸟-ASP.NET 总结
- JSP中使用SIteMesh实现类似asp.net母版效果
- 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(转)
- Js 给asp.net 控件赋值
- asp.net页面之间的跳转
- ASP.NET中将声音文件添加到资源中并进行播放的方法
- ASP.NET 3.5 MVC框架深度解析
- 【asp.net】常用内置对象(Request,Response、server、Cookies)
- ASP.NET - Web.config文件详解
- ASP.NET - 出错页
- ASP.NET - 在线编辑器(FreeTextBox)
- 【asp】【07】asp判断session是否存在的四种方法
- [ASP.NET MVC 小牛之路]02 - C#知识点提要
- JasperReport学习笔记(一)
- [ASP.NET MVC 大牛之路]01 - C#高级知识点概要(1) - 委托和事件
- 这算是ASP.NET MVC的一个大BUG吗?
- asp.net mvc多级目录结构和多级area实现技巧