strcpy系列字符串处理函数的常见误用及正确使用方法

最近项目有好几个由于字符串处理函数使用不当引起的崩溃,虽然这些函数很基础也很常用,但也比较容易误用,轻则由安全CRT函数在第一现场崩溃,重则造成Buffer Overflow,带来不可预测的错误。借分析这几个dump的机会,并且参考了上一些网上资料,总结了这几个函数几点常见误用及正确使用方法,希望可以帮助大家减少对这些函数的误用,有兴趣的同学可以看看。

 

先上一个dump,这个dump比较简单,有经验的一眼就可以看出崩溃的原因来

根据崩溃处指令可以知道是因为wcscpy_s函数检测到了错误而主动抛出了异常,再看看栈回溯

根据栈回溯可以看到wcscpy_s函数的目标缓存大小为260也就是MAX_PATH,再看一下源字符串内容

cid:image007.png@01CEC92E.879D3AB0

源字符串大小刚好为260,刚刚好等于目标缓存大小,但加上结尾符实际长度为261,看一下wcscpy_s函数的反汇编代码

cid:image008.png@01CEC930.749A1030

根据wcscpy_s函数的反汇编代码可以知道,当目标缓存区大小(这里指参数传进去的大小)无法容纳源字符串时,wcscpy_s函数将主动抛出异常。

 

接下来总结几点wcscpy系列(strcpy类似)字符串常见误用常见误用及正确使用方法:

1.     wcscpy,函数本身没安全性可言,容易造成Buffer Overflow,强烈不建议使用

2.     wcsncpy,函数原型 wchar_t *wcsncpy( wchar_t *strDest, const wchar_t *strSource, size_t count )wcscpy相比,多了一个count参数,这个参数指定的是要拷贝的字符数,但要注意的是
,这个函数实际上并没有我们认为的那么安全,如果我们指定的count数大于目标缓冲区的大小,那么结果会是灾难性的,因为wcsncpy会完整的写满count个字符(不够的用\0填充),反汇编如下:
cid:image009.png@01CEC936.DBD7C110
另处还有一点要注意的是,当源字符串大于count时, wcsncpy不会往后面添上\0,造成不可预测的结果,比如很容易像以下方法使用该函数:
PSa. wcsncpy会完整的写满count个字符,不够的用\0填充
    b.count无法容纳源字符串时,wcsncpy不会往后面添上\0

3.     wcscpy_swcscpy_s 函数原型为errno_t __cdecl wcscpy_s(_Out_z_cap_(_DstSize) wchar_t * _Dst, _In_ rsize_t _DstSize, _In_z_ const wchar_t * _Src)

根据前面wcscpy_s函数的反汇编代码可以知道,当目标缓存区大小(这里指参数传进去的大小)无法容纳源字符串时,wcscpy_s函数将主动抛出异常。

4.     wcsncpy_swcsncpy_s 函数原型为errno_t __cdecl wcsncpy_s(_Out_z_cap_(_SizeInWords) wchar_t * _Dst, _In_ rsize_t _SizeInWords, _In_z_ const wchar_t * _Src, _In_ rsize_t _MaxCount)_MaxCount指定最大拷贝字符数,

根据wcsncpy_s的反汇编,可以很清楚地知道wcsncpy_s的处理逻辑

cid:image010.png@01CEC93E.ADB9E6C0

跳出循环后反汇编如下

 

总结:

1.     尽量使用wcsncpy_s函数,wcscpy_swcsncpy都是不安全的

2.     尽量将判断逻辑放在程序里面,而不要让wcsncpy_s抛出异常

 

PS:wcscat系列函数跟wcscyp类似

但有点需要注意的是errno_t __cdecl wcsncat_s(_Inout_z_cap_(_SizeInWords) wchar_t * _Dst, _In_ rsize_t _SizeInWords, _In_z_ const wchar_t * _Src, _In_ rsize_t _MaxCount)中的_SizeInWords指的目标字符串的大小,包括字符串中已经存在字符,线上有个dump因为没考虑已经存在的字符而导致该函数抛出异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值