如何安全动态格式化字符串

原创 2004年09月14日 13:03:00

在C语言中,我们如果希望进行格式化进行输出,一般我们用 sprintf 来字符串。

例如:
char temp[100];
sprintf(temp, "%s", "HelloWorld"  );

通常上面的操作应该没有任何问题。但是,在某些情况下,是有意想不到的结果产生。
比如:在进行出错信息进行输出时,我们采取如下写法:

char temp[64];
sprintf( temp, "Error at file %s , line %d , column %d , Message: %s", strFile, lineNumber, columnNumber, strMessage);

一般情况下,如果出错信息较少,上面程序没有任何问题,如果出错信息很长,上面的数据会越界,从而导致改写其他内存中的内容,引发一些你想象不到的错误。
这时,估计你的解决方案就是增大temp的空间,比如:temp[1000]。
没错,这样改正之后,造成上面出错的概率会较少很多,但是还没有完全解决此问题。
在用户如果提供比较多的出错信息时,还是有问题产生。
那么我们有没有办法来完全解决此问题呢????

在C++中,有个string类,可以用来动态存储字符串,它会根据当前字符串的长度来调整它的长度。
且string.begin() 相当于char*指针。

说到这,你是不是有一种冲动改写上面的程序?( I so ).

string strTemp;
strTemp.reserve(64); //优化string的内存分配策略
sprintf( strTemp.begin(), "Error at file %s , line %d , column %d , Message: %s", strFile, lineNumber, columnNumber, strMessage);

编译通过,^_^(窃喜) ! 

测试一下,在较短的出错消息(没有超过64)时,没有任何问题,但是在超过64之后,会进行出错!!!(是不是比上面的比较‘安全’? )

为什么上面会出错???string 不是动态进行扩展存储空间吗?

没错,如果超过64之后,string会进行动态分配空间,由于string一般确保它的存储空间连续性,所以它是重新分配一块足够大的空间,然后将数据copy过去,这个过程类似于realloc 来分配空间。这必然导致我们现在的string.begin()和以前的begin()所指向的地址不一样。
而我们sprintf指向的地址是以前的string.begin(),不是重新分配之后的空间,一般以前分配的空间会被释放,所以会导致程序出错。

哪我们还有没有别的办法来改善上面的问题???

MFC中的CString类有个成员函数Format就可以用来格式化字符串,并且可以动态扩展此字符串。
是不是很酷???

但是,对于我来说,凡是不在UI地方(即界面显示部分),尽量避免使用MFC中的内容,使得以后的移植比较方便(可能有点杞人忧天的感觉),嘿嘿!!

难道就没有别的解决方案???
毕竟格式化字符串是非常常见的事情,连C中都有一个特定的函数来完成(sprintf)。难道C++里面就没有解决方案吗?

记得在C++的IO输出流中,标准的cout,就可以用来格式化输出到屏幕。
如果是fstream就可以用于格式化输出到文件中。(说到这里,好像记得有个字符串流?)

赶快进行msdn搜索,呵呵,找到了这个家伙。

不再多说了,直接进行示例.

    std::ostringstream strOut( ios_base::out);

    strOut << "Error at file " << file
    << " line " << lineNumber << " column " << columnNumber << endl;
   
   strOut << " Message:" << CErrorMsg(errorCode).getErrorMsg() << endl;
   strOut << " UserMessage: " << errStr << endl;

   然后我们可以把上面的字符串提取出来.
   string strValue =  strOut.str();

   到了这一步,你应该知道如何来使用string类型的值了吧。

   呵呵,终于将它进行解决了,并且解决的如此彻底( 嘘,不要告诉别人,告诉你一个秘密,以前碰到此问题,没有很好的进行解决过,只是适当的将temp的数组增大,即将出错的概率进行了降低!)。

  
   什么??? 你无法编译???? 加入相关头文件不就可以了吗???不知道哪个头文件,那去msdn中查找啊。
   什么你没有查到?耐心一点会有的(不过在比较隐蔽的地方)。

   Use <sstream> to work with objects of type basic_string.
   Use <strstream> work with char *, which are C strings

 即:在上面中,我们只要加入下面一句就可以了:
     #include <sstream>

Java字符串格式化

常规类型的格式化String类的format()方法用于创建格式化的字符串以及连接多个字符串对象。熟悉C语言的同学应该记得C语言的sprintf()方法,两者有类似之处...
  • axi295309066
  • axi295309066
  • 2016年10月15日 01:49
  • 999

c语言中的格式化字符串

C语言中格式字符串的一般形式为: %[标志][输出最小宽度][.精度][长度]类型, 其中方括号[]中的项为可选项。 一、类型 我们用一定的字符用以表示输出数据的类型,其格式符和意义下表所示:...
  • MyLinChi
  • MyLinChi
  • 2016年11月10日 16:09
  • 1985

Android通过String.format格式化(动态改变)字符串资源的显示内容

一、实现效果: 最近在项目中需要做类似于上图显示的效果,里面的数字和称谓是动态获取的,对于这种显示效果,有如下两种解决方案来处理: (1)通过代码动态设置TextView的内容,比如: /** ...
  • zmywly
  • zmywly
  • 2014年09月15日 10:49
  • 10723

ISCC之pwn1格式化字符串漏洞详解!

作为小白的我,自从入了ctf的坑就再也没爬起来过,从无到有实在是很辛苦。仅以此片纪念我的青春。   直接进入正题。这是个很明显的32位的格式化字符串漏洞。 上手就先leak出libc地址,求偏移得到...
  • qq_33438733
  • qq_33438733
  • 2017年05月29日 19:46
  • 504

sscanf()--字符串格式化输入

sscanf() 的作用:从一个字符串中读进与指定格式相符的数据. 原型: int sscanf (const char str,const char format,……..); 说明: ssc...
  • gao1440156051
  • gao1440156051
  • 2015年09月06日 21:56
  • 1233

Python——字符串格式化与字符串操作

一、字符串格式化使用字符串格式化操作符%实现,格式化操作符的右操作数可以是元组或者映射类型。如果右操作数是元组,其中每一个元素都会被单独格式化,而且每个值都需要一个对应的转换说明符。 基本的转换说明...
  • u010480899
  • u010480899
  • 2016年10月03日 19:25
  • 640

格式化字符串漏洞简介

简介格式化字符串,也是一种比较常见的漏洞类型。
  • PrettyDay
  • PrettyDay
  • 2015年12月20日 23:27
  • 4440

C/C++格式化字符串说明

C/C++格式化字符串说明 1. 格式化规定符 ━━━━━━━━━━━━━━━━━━━━━━━━━━    符号                  作用 ───────────────...
  • bzhxuexi
  • bzhxuexi
  • 2014年04月29日 22:44
  • 2662

字符串和格式化输入/输出

字符串就是一个或多个字符的序列。双引号不是字符串的一部分,它们只是通知编译器其中包含了一个字符串。 C没有为字符串定义专门的变量类型,而是把它存储在char数组中。 字符串中的字符存放在相邻的存储单元...
  • Burgdan
  • Burgdan
  • 2016年08月27日 01:33
  • 727

C# 各种格式化字符串

 1、格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元) string.Format("{0:C}",0.2) 结果为:¥0.20 (英文操作系统结果:$0.20) ...
  • qq61394323
  • qq61394323
  • 2016年12月06日 09:58
  • 1136
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何安全动态格式化字符串
举报原因:
原因补充:

(最多只允许输入30个字)