C语言字符串处理函数

 简单说来,现有的 C 语言运行时函数实在难以在当今充斥着恶意攻击企图的大环境下立足。这些函数要么在返回值和参数上缺乏一致性,要么隐含着所谓的"截断误差"(truncation errors) 错误,要么无法提供足够强大的功能。坦言之,调用这些函数的代码太容易产生"内存溢出"问题了。
   
    面向 C++ 程序员的类足以应付各种 安全处理字符串的编程需要;他们能够选择 MFC 的Cstring 类、ATL 的CComBSTR 类 或者STL 的string 类,等等。然而,经典的 C 语言程序仍然普遍地存在,许多人正在把 C++ 当作 "改良的 C 语言" 来用,却把丰富的 C++ 类束之高阁。
   
    其实只需要添加一行代码,你就能在 C 语言代码中调用 安全性良好的 strsafe 系列函数了,这些新函数包含在一个头文件和一个函数库(可选)中,而后两者能在新版的 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 系列函数来实现更加高级的功能,比如:
   
    获取目标缓冲区的当前指针。
   
    获取目标缓冲区的剩余空间长度。
   
    以某个特定字符填充空闲缓冲区。
   
    一旦字符串处理函数失败,就把用特定值填充字符串。
   
    一旦字符串处理函数失败,就把目标缓冲区设成 NULL .
   
    如此改进后的代码性能又如何呢?它与原先的代码在性能上几乎没有差别。在 测试中,调用 Ex 版本的 strsafe 系列函数的程序会在调用失败时把缓冲区设为 NULL ,并以 0xFE 作为填充字节,代码如下:
   
    DWORD dwFlags = STRSAFE_NULL_ON_FAILURE | STRSAFE_FILL_BYTE(0xFE);其中设置填充字节的代码耗时较多。事实上,如果这里仅仅把缓冲区设置为 NULL 的话,则采用 Ex 版本的 strsafe 系列函数的代码将会与采用普通的 strsafe 系列函数的代码耗时相同。
   
    还有一点值得引起注意:当你引用 strsafe 系列函数时,原有的 C 语言字符串处理函数都将被自动进行 #undef 处理。这也没问题,因为调试过程中的出错信息将会告诉你哪些函数已经被相应的 strsafe 系列函数取代了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值