用于检测将 wchar_t* 传递给 BSTR 的静态代码分析

发布于 2024-12-28 18:44:51 字数 1170 浏览 1 评论 0原文

由于 BSTR 只是 wchar_t*typedef,我们的代码库有几个(很多?)地方将字符串文字传递给期望的方法BSTR 这可能会扰乱编组器或任何尝试使用任何 BSTR 特定方法(例如 SysStringLen)的人。

有什么方法可以静态检测这种类型的误用吗?

我尝试使用 VC10 /Wall 和静态代码分析 Microsoft All Rules 进行编译,但以下有问题的代码片段不会被任何一个标记其中。

void foo(BSTR str)  
{
    std::cout << SysStringLen(str) << std::endl; 
}

int _tmain()
{
    foo(L"Don't do that");
}

更新:在尝试破坏wtypes.h以检测此类违规行为后,我已经放弃了。

我尝试了两条路径,这两条路径都可以使用上面的示例程序,但是一旦我尝试了一个真正的项目,它们就失败了。

  1. 创建一个名为 BSTR 的类,但由于 VARIANT 有一个 BSTR 作为联合成员,因此新类不能有任何构造函数或赋值运算符破坏了 NULL 被视为 BSTR 的每个地方。我尝试用具有转换运算符的类型替换 NULL,但在添加了数十个新运算符(比较、转换等)后,我开始遇到不明确的调用并放弃了。
  2. 然后我尝试了@CashCow和@Hans建议的方法(使BSTR成为另一种类型的指针的typedef)。在添加 toBSTRfromBSTR 方法并乱扔 comutil.h (_bstr_t) 和其他有转换的地方我终于到了编译器因 IDL 生成的标头而窒息的地步(默认值被转换为文字宽字符串)。

简而言之,我已经放弃尝试自己实现这一目标,如果有人知道可以提供帮助的代码分析工具,我会很高兴听到它。

Since a BSTR is only a typedef for wchar_t* our code base has several (many?) places where string literals are passed to a method expecting a BSTR this can mess up with marshallers or anyone who tries to use any BSTR specific method (e.g. SysStringLen).

Is there any way to statically detect this type of misuse?

I tried compiling with VC10 /Wall and with static code analysis Microsoft All Rules but the following offending piece of code doesn't get flagged by either of them.

void foo(BSTR str)  
{
    std::cout << SysStringLen(str) << std::endl; 
}

int _tmain()
{
    foo(L"Don't do that");
}

Update: After trying to vandalize wtypes.h into detecting these kinds of transgressions I've given up.

I tried two paths, both of which I got to work with my sample program above but once I tried a real project they failed.

  1. create a class named BSTR but since a VARIANT has a BSTR as a union member the new class couldn't have any constructors or assignment operators this broke every place were NULL was treated as a BSTR. I tried to replace NULL with a type that has conversion operators but after adding dozens of new operators (comparison, conversion etc.) I started to run into ambiguous calls and gave up.
  2. I then tried the way suggested by @CashCow and @Hans (makeing BSTR a typedef to another type of pointer). That didn't work either, after adding toBSTR and fromBSTR methods and littering comutil.h (_bstr_t) and other places with conversions I finally got to the point where the compiler choked at headers produced from IDLs (default values are translated to literal wide strings).

In short I've given up on trying to achieve this on my own, if anyone knows of a code analysis tool that can help I would be very happy to hear about it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

记忆消瘦 2025-01-04 18:44:51

我相信 Coverity 声称可以检测此类漏洞。我记得他们在向我工作的公司演示时特别提到了 COM 的东西。

他们的 数据表 似乎暗示他们会检查 BSTR 使用不当的类别。他们有一个演示期;您可以尝试一下,看看它是否标记了您的示例输入。

I believe Coverity claims to detect these sorts of vulnerabilities. I remember them mentioning COM stuff specifically when they demo'd to a company I worked for.

Their datasheet certainly seems to imply they check for classes of improper BSTR usage. They have a demo-period; you could try it and see if it flags your sample input.

ゝ偶尔ゞ 2025-01-04 18:44:51

您是否可以更改方法以采用 _bstr_t 或 CComBSTR 代替?

如果不是,那么因为文字在技术上是 const wchar_t *,如果有编译器设置不允许文字 -> 非 const 指针转换,那么你可以这样做。

否则,可以将 BSTR 的定义修改为 unsigned Short *。然后,如果您构建所有源代码,则无论传入文字的任何地方都会出现编译器错误,并且您可以修复所有这些代码。那我建议还是改回来吧...

Are you able to change your methods to take _bstr_t or CComBSTR instead?

If not then as a literal is technically a const wchar_t *, if there is a compiler setting to not allow literal->non-const pointer conversion then you can do that.

Failing that, there is a possibility of modifying the definition of BSTR to be unsigned short *. Then if you build all your source, you will get compiler errors wherever a literal is being passed in and you can fix all this code. Then I would suggest changing it back...

扶醉桌前 2025-01-04 18:44:51

你可以尝试用Clang编译,它的静态/动态分析可能会找到你要找的东西。

You may try compiling with Clang, it's static/dynamic analysis may find what you are looking for.

放肆 2025-01-04 18:44:51

使用 BSTR 重载所有函数并通过适当的转换转发它们。

void foo( BSTR str )
{
    std::cout << SysStringLen(str) << std::endl; 
}

void foo( const WCHAR *str )
{
    foo( SysAllocString( str ));
}

int _tmain()
{
    foo( L"don't do this" );
    return 0;
}

或者,要生成编译器错误,请将所有参数类型从 BSTR 更改为其他类型并查找错误:

typedef UINT bar;

void foo( bar _str )
{
    // make the compiler happy below
    BSTR str = (BSTR)_str;
    std::cout << SysStringLen(str) << std::endl;
}

int _tmain()
{
    foo( L"don't do this" );
    foo( (bar)42 );
    return 0;
}

错误 C2664: 'foo' : 无法将参数 1 从 'const wchar_t [14]' 转换为 'bar'

我假设 C2664 错误和编译器识别的“const wchar_t[]”类型是您希望编译器为使用 BSTR 对函数进行的每个内部调用找到的类型?

Overload all functions with the BSTR and forward them with the appropriate conversion.

void foo( BSTR str )
{
    std::cout << SysStringLen(str) << std::endl; 
}

void foo( const WCHAR *str )
{
    foo( SysAllocString( str ));
}

int _tmain()
{
    foo( L"don't do this" );
    return 0;
}

Or, to generate compiler errors, change all of the parameter types from BSTR to something else and look for the errors:

typedef UINT bar;

void foo( bar _str )
{
    // make the compiler happy below
    BSTR str = (BSTR)_str;
    std::cout << SysStringLen(str) << std::endl;
}

int _tmain()
{
    foo( L"don't do this" );
    foo( (bar)42 );
    return 0;
}

error C2664: 'foo' : cannot convert parameter 1 from 'const wchar_t [14]' to 'bar'

I assume the C2664 error and the 'const wchar_t[]' type identified by the compiler is what you want the compiler to find for every internal call made to the function using the BSTR?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文