13

由于 aBSTR只是 atypedef对于wchar_t*我们的代码库有几个(很多?)地方,其中字符串文字被传递给期望 a 的方法,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,但由于 aVARIANT有 aBSTR作为联合成员,因此新类不能有任何构造函数或赋值运算符,这破坏了每个地方都NULL被视为 a BSTR。我尝试用NULL具有转换运算符的类型替换,但在添加了数十个新运算符(比较、转换等)后,我开始遇到模棱两可的调用并放弃了。
  2. 然后我尝试了@CashCow 和@Hans 建议的方式(制作BSTRtypedef一种类型的指针)。这也不起作用,在添加toBSTRfromBSTR方法并乱扔comutil.h ( _bstr_t) 和其他带有转换的地方之后,我终于到了编译器在 IDL 生成的头文件中窒息的地步(默认值被转换为文字宽字符串)。

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

4

4 回答 4

4

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

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

于 2012-03-08T00:56:21.790 回答
1

您可以尝试使用 Clang 进行编译,它的静态/动态分析可能会找到您要查找的内容。

于 2012-02-03T19:56:13.730 回答
1

你能改变你的方法来代替 _bstr_t 或 CComBSTR 吗?

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

否则,有可能将 BSTR 的定义修改为 unsigned short *。然后,如果您构建所有源代码,无论在哪里传入文字,您都会收到编译器错误,您可以修复所有这些代码。那我建议改回来...

于 2012-01-24T12:19:37.250 回答
0

使用 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 对函数进行的每个内部调用找到的内容?

于 2012-02-01T20:56:22.273 回答