首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

传递一个比实际字符串大的缓冲区长度会怎么样?

如果你在 Win32 的世界摸爬滚打过几年,则你会发现:很多函数如果要传入一个源字符串,则通常会有两个参数,一个是字符串缓冲区指针,另一个是字符串缓冲区长度。

如果传递的缓冲区长度,大于实际的字符串长度,则结果和函数的内部实现相关。

一些函数在给定字符串和长度时,会在长度用尽或者遇到空终止符时停止,以先到者为准。

举个例子,我们看一下 StringCchCopyN 的函数原型:

STRSAFEAPI StringCbCopyNA(

[out] STRSAFE_LPSTR pszDest,

[in] size_t cbDest,

[in] STRSAFE_PCNZCH pszSrc,

[in] size_t cbToCopy

);

如果你将 cbToCopy 设置为大于字符串长度的值传递给 StringCchCopyN 函数,它会在空终止符处停止。

另一方面,许多其他功能(尤其是 NLS 系列中的功能)会在你要求它们时愉快地继续操作空字符。

这里的想法是,既然你传递了明确的大小,那么你有意识地在操作一个可能包含嵌入的空字符的缓冲区。毕竟,如果你传递了明确的源大小,那么你是真的有意这样做,对吗?

也许你正在操作一个支持嵌入空字符的 BSTR, 要获取 BSTR 的大小,你必须使用类似 SysStringLen 的函数。

如果你调用 CharUpperBuff(psz, 20), 那么该函数确实会将从 psz 开始的 20 个 TCHAR 转换为大写。

如果 psz[10] 处恰好有一个空字符,该函数将将该空字符转换为大写,并继续转换接下来的十个 TCHAR。

我曾见过程序崩溃,因为它们认为像 CharUpperBuff 和 MultiByteToWideChar 这样的函数在遇到空值时会停止运行。例如,有人可能会写成:

// 有问题的代码 – 请看后面的解释

void someFunction(char *pszFile)

{

CharUpperBuff(pszFile, MAX_PATH);

… do something with pszFile …

}

void Caller()

{

char buffer[80];

sprintf(buffer, “file%d”, get_fileNumber());

someFunction(buffer);

}

这里的意图是让 someFunction 在操作之前将字符串转换为大写,最多处理 MAX_PATH 个字符,但实际上发生的是从pszFile 开始的 MAX_PATH 个字符被转换,即使实际缓冲区较短!

由于这是一个栈缓冲区,因此超出缓冲区末尾的 220 个字符很可能包括返回地址。结果:程序崩溃。

如果短缓冲区是在堆上分配的,情况会更有趣。那么它不会破坏返回地址(你可能会在函数返回后立即注意到),而是会破坏堆,这通常在调用函数离开现场很久之后才会导致崩溃。这就更加难以调试了。

请考虑一下这个替换函数:

// 有问题的代码 – 请不要使用

int invariant_strnicmp(char *s1, char *s2, size_t n)

{

return CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE,

s1, n, s2, n) – CSTR_EQUAL;

}

总结

在 Win32 Native 编程中,惯用法是一套很重要的用于提升编码安全性的规则工具箱。

如果经过严格的测试,确认一段代码能正常稳定工作,请将这段代码收藏到你的惯用法工具箱,并在以后的开发中时常拿出来使用。

关于这一点,我可以举一个我在开发 拓扑梅尔智慧办公平台(TopomelBox) 时的一个例子。

例如如果需要传递一个字符串数组长度,则我会始终使用 _countof(ArrayBuffer) 这样的惯用法来传递数组长度,而不是手动指定长度。

掌握越来越多的惯用法之后,我终于可以安稳的睡满整个晚上了。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。

本文来自:《What happens if you pass a source length greater than the actual string length?》

最近我写了个东西

正如你们所知道的,拓扑梅尔智慧办公平台(TopomelBox)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。

我想:你值得拥有。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OivliFC0iX3hs8qf-yufthFA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券