Статический анализ кода для обнаружения передачи wchar_t * в BSTR - PullRequest
13 голосов
/ 24 января 2012

Поскольку BSTR - это всего лишь typedef для wchar_t*, у нашей кодовой базы есть несколько (много?) Мест, где строковые литералы передаются методу, ожидающему BSTR, что может привести к путанице с маршаллерами или кем-либо, ктопытается использовать любой BSTR специфический метод (например, SysStringLen).

Есть ли какой-либо способ статически обнаружить этот тип неправильного использования?

Я попытался скомпилировать с VC10 /Wall и сстатический анализ кода все правила Microsoft , но следующий нарушающий код не помечается ни одним из них.

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 a typedef для другого типа указателя).Это тоже не сработало, после добавления toBSTR и fromBSTR методов и мусора comutil.h (_bstr_t) и других мест с преобразованиями я наконец-то дошел до того, что компилятор захлебнулся заголовкамисоздается из IDL (значения по умолчанию переводятся в буквально широкие строки).

Короче говоря, я перестал пытаться достичь этого самостоятельно, если кто-нибудь знает инструмент анализа кода, который может помочьЯ был бы очень рад услышать об этом.

Ответы [ 4 ]

3 голосов
/ 08 марта 2012

Я считаю, Coverity утверждает, что обнаружил такого рода уязвимости.Я помню, как они упоминали о COM, особенно когда они делали demo'd для компании, в которой я работал.

Их таблица данных определенно подразумевает, что они проверяют классы неправильного использования BSTR.У них есть демо-период;Вы можете попробовать и посмотреть, помечает ли он ваш пример ввода.

1 голос
/ 03 февраля 2012

Вы можете попробовать скомпилировать с Clang, это статический / динамический анализ может найти то, что вы ищете.

1 голос
/ 24 января 2012

Можете ли вы изменить свои методы, взяв вместо них _bstr_t или CComBSTR?

Если нет, то в качестве литерала технически это константный wchar_t *, если есть настройка компилятора, запрещающая литерал-> не-Преобразование указателя const, тогда вы можете сделать это.

Если это не так, есть возможность изменить определение BSTR, чтобы оно было коротким без знака *.Затем, если вы соберете весь свой исходный код, вы получите ошибки компилятора везде, где передается литерал, и вы можете исправить весь этот код.Тогда я бы предложил изменить его обратно ...

0 голосов
/ 02 февраля 2012

Перегрузите все функции с помощью 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?

...