Strsafe.h:更安全的C语言字符串处理函数
2010-10-10 14:53:15 来源:WEB开发网简单说来,现有的 C 语言运行时函数实在难以在当今充斥着恶意攻击企图的大环境下立足。这些函数要么在返回值和参数上缺乏一致性,要么隐含着所谓的“截断误差”(truncation errors) 错误,要么无法提供足够强大的功能。坦言之,调用这些函数的代码太容易产生“内存溢出”问题了。
我们发现,面向 C++ 程序员的类足以应付各种安全处理字符串的编程需要;他们能够选择 MFC 的Cstring 类、ATL 的CComBSTR 类 或者STL 的string 类,等等。然而,经典的 C 语言程序仍然普遍地存在,何况许多人正在把 C++ 当作 “改良的 C 语言” 来用,却把丰富的 C++ 类束之高阁。
其实只需要添加一行代码,你就能在 C 语言代码中调用安全性良好的 strsafe 系列函数了,详细请参阅:
《Using the Strsafe.h Functions》:http://msdn.microsoft.com/en-us/library/ms647466.aspx
这些新函数包含在一个头文件和一个函数库(可选)中,而后两者能在新版的 Platform SDK 中找到。对,就这么简单:
#include "strsafe.h"
还等什么呢!
再强调一次,对 strsafe 函数库的引用是可选的。
为了实现 strsafe 系列函数的目标,你的代码必须满足下列条件:
始终以 NULL 字符结束字符串。
始终检测目标缓冲区的长度。
始终用 HRESULT 语句产生统一的返回值。
兼顾 32 位与 64 位两种运行环境。
具有灵活性。
我们觉得,缺乏统一性是导致现有许多 C 语言字符串处理函数容易产生安全漏洞的根本原因,而 strsafe 系列函数所带来的高度统一性恰恰是解决此问题的一剂良药。然而,strsafe 也不是万能药。单纯依靠 strsafe 系列函数并不能保证代码的安全性和坚固性——你还必须开动你的大脑才行——然而这样对解决问题还是大有帮助的!
下面给出一段采用经典 C 语言运行时间函数的代码:
void UnsafeFunc(LPTSTR szPath,DWORD cchPath) { TCHAR szCWD[MAX_PATH]; GetCurrentDirectory(ARRAYSIZE(szCWD), szCWD); strncpy(szPath, szCWD, cchPath); strncat(szPath, TEXT("\"), cchPath); strncat(szPath, TEXT("desktop.ini"),cchPath); }
以上代码中的 bug 随处可见 —— 它没有检查任何一个返回值,而且在对 strncat 函数的调用中也没有正确地使用 cchPath (因为MAX_PATH 中保存的是目标缓冲区内剩余空间的长度,而不是目标缓冲区的总长度)。于是,“内存溢出” 问题将会快找上门来。然而,象这样的代码片段早已泛滥成灾了。如果改用 strsafe 系列函数,那么以上代码应该变成:
bool SaferFunc(LPTSTR szPath,DWORD cchPath) { TCHAR szCWD[MAX_PATH]; if (GetCurrentDirectory(ARRAYSIZE(szCWD), szCWD) && SUCCEEDED(StringCchCopy(szPath, cchPath, szCWD)) && SUCCEEDED(StringCchCat(szPath, cchPath, TEXT("\"))) && SUCCEEDED(StringCchCat(szPath, cchPath, TEXT("desktop.ini")))) { return true; } return false; }
这段代码不但检查了每一个返回值,还保证了适时传入同一目标缓冲区的总长度。你还可以采用 Ex 版本的 strsafe 系列函数来实现更加高级的功能,比如:
获取目标缓冲区的当前指针。
获取目标缓冲区的剩余空间长度。
赞助商链接