Подтвердить что ты не робот

Анализ статического кода для обнаружения прохождения wchar_t * в BSTR

Так как a BSTR является только typedef для wchar_t*, наша база кода имеет несколько (много?) мест, где строковые литералы передаются методу, ожидающему 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 для обнаружения таких видов нарушений я отказался.

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

  • создайте класс с именем BSTR, но поскольку VARIANT имеет BSTR в качестве члена объединения, новый класс не может иметь никаких конструкторов или операторов присваивания, которые были разбиты на все места, NULL рассматривался как BSTR. Я попытался заменить NULL на тип, который имеет операторы преобразования, но после добавления десятков новых операторов (сравнение, преобразование и т.д.) Я начал сталкиваться с неоднозначными вызовами и сдавался.
  • Затем я попробовал способ, предложенный @CashCow и @Hans (make BSTR a typedef для другого типа указателя). Это также не сработало, добавив методы toBSTR и fromBSTR и засорив comutil.h(_bstr_t) и другие места с конверсиями. Наконец, я дошел до того момента, когда компилятор задохнулся в заголовках, созданных из IDL (значения по умолчанию переводятся в буквальные широкие строки).

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

4b9b3361

Ответ 1

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

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

Ответ 2

Можете ли вы изменить свои методы, чтобы вместо этого использовать _bstr_t или CComBSTR?

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

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

Ответ 3

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

Ответ 4

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