-1

编写这样的代码是否有任何错误:

char* sp=(char*)malloc(128);
int x=22;

wsprintf(sp,"%d",x);
cout<<sp;

我特意询问安全错误?

4

4 回答 4

3

这里有许多“潜在”问题,实际上没有一个问题是在欺骗任何东西,但您可能会发现事情的表现与您预期的不一样。

首先:wsprintf,作为 Win32 API ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550(v=vs.85).aspx ) 原型如下:

int __cdecl wsprintf(
  _Out_  LPTSTR lpOut,
  _In_   LPCTSTR lpFmt,
  _In_    ...
);

whereLPTSTR被定义为char*wchar_t*取决于UNICODE符号的定义(检查您的项目设置和/或构建命令)

现在,如果您使用的是 ANSI 构建(无 UNICODE),所有类型都是一致的,但没有检查 wsprintf 写入的内容是否超过您分配的 128 个字符。如果你只写一个十进制整数,它不会有问题,但如果你(你之后的其他人)稍后修改“消息”并且没有进行检查,可能会出现一些意外(比如wsprintf(sp,"This is the number I've been told I was supposed to be expected to be: %d",x);这仍然适合 128 个字符吗?! ?)

如果您使用的是 UNICODE 构建,则分配 128 个字符,并在其上写入一个双字节字符串。数字 22 将被写为\x32\x00\x32\x00\x00\x00(3200 是 0x0032 的小端编码,它是对应于 UNICODE 50 的 wchar_t,代表“2”)。如果您将该序列提供给 cout(即基于 char,而不是基于 wchar_t),则会将第一个 \x00 视为字符串终止符,并将输出......只是“2”。

为了保持连贯性,您可以:

  • 使用所有char基于类型和函数(OK malloc 和 cout,但wsprintfA不是wsprintf
  • 使用所有wchar_t基于类型和函数(malloc(128*sizeof(wchar_t))、wchar_t* 和wsprintfW)
  • 使用所有TCHAR基于类型(malloc(128*sizeof(TCHAR))、TCHAR* 和 wsprintf,但定义tcoutcoutwcout取决于 UNICODE)。
于 2012-10-31T15:04:18.813 回答
1

There is no security mistake because it is never the case that an int converted to a C string will exceed the size you've allocated.

However this style of programming has the potential for security issues. And history has shown that this kind of code has caused real security issues time and time again. So maybe you should be learning a better style of coding?

于 2012-10-31T11:53:48.443 回答
0

Ok given that you have stated you are using winapi, read this from their documentation:

Note Do not use. Consider using one of the following functions instead: StringCbPrintf, StringCbPrintfEx, StringCchPrintf, or StringCchPrintfEx. See Security Considerations.

Therefore do not use. I would ignore however what they tell you to do instead and either:

  1. Write in C, and a function from the C standard library (sprintf, snprintf etc). In that case you cannot use cout.

  2. Write in C++. Use std::string and there is even a new to_string, as well as boost::format and ostringstream to help you build formatted string. You can still use C standard library functions there if you want to as well when it really suits your purpose better, but leave the allocation stuff to the library.

于 2012-10-31T11:53:59.977 回答
0

这个 MSDN 链接列出了使用wsprintf. 它们似乎不适用于您的示例,但它们确实提供了一些您可能想要探索的替代方案。

于 2012-10-31T12:33:13.903 回答