Pull to refresh

Народ против PVS-Studio: дубль первый

Designing and refactoring *
Добрый вечер Хабранарод!

Воодушевленный этим постом и Хабрасообществом, предлагаю вам свой вариант анализа хорошо пропиаренной утилиты (как примечательно выразился Wo1f) — PVS-Studio.

В качестве примечания, использовал Visual Studio 2010 (крэкнутый, конечно) и скачал PVS-Studio из официального сайта, нажимая «Download and Try» и следуя инструкциям. Все это я пишу потому, что у меня вопросы на счет данной утилиты и требуется ваша, так сказать, помощь.

Первым делом прогоняем тесты из предудущей статьи, и так:

Тест 1:

int main()
{
	vector<int> v;
	v.reserve(2);
	assert(v.capacity() == 2);
	v[0];
	v[0] = 1;
	v[1] = 2;
	cout << v[0] << endl;
	v.reserve(100);
	cout << v[0] << endl;
	return 0;
}

VS2010: ничего
PVS-Studio: ничего

Тест 2:

void prettyFormat(int i, char* buf)
{
    sprintf(buf, "%4d", i);
}

int main()
{
    vector<int> v;
    v.reserve(2);
    //....
    char buf[5];
    prettyFormat(10, buf);
    return 0;
}

VS2010: warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
PVS-Studio: ничего

Тест 3:

int* prettyFormat(int i, char* buf)
{
    sprintf(buf, "%4d", i);
    int* a;
    return a;
}

int main()
{ 
    ...

VS2010: warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
warning C4700: uninitialized local variable 'a' used

PVS-Studio: ничего

Тест 4:

int* prettyFormat(int i, char* buf)
{
    sprintf(buf, "%4d", i);
    int* a;
    fopen("filename", "r");
    char buf2[5];
    strcpy(buf2, buf);
    return a;
}

VS2010: Кроме предыдущих двух, warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.

PVS-Studio: ничего

Вот здесь и мой вопрос: почему PVS-Studio ничего не выдает, у меня включены все три уровни «выдачи». Может я что-то делаю не так? (Из меню выбираю PVS-Studio -> Check Solution), не смейтесь если я не умею «пользоваться» утилитой.

Новые тесты

И так, продолжаем. Простейший пример, что пришло в голову:
char buf[32];
strncpy(buf, data, strlen(data));

PVS-Studio опять молчит, а Visual Studio опять предупреждает о возможной проблеме при использовании «небезопасной» функции, в данном случае — strncpy().
В чем же реальная проблема? Проблема в классическом переполнении буфера, ошибка, из-за которой многие разлюбили C/C++, а остальные нашли повод выступать против этих прекрасных языков. В данном примере в качестве последнего аргумента функции strncpy передана длина входного буфера, а не размер целевого!

Следующий тест более «профессионального» уровня, в нем акцент делается на многопоточости. Фрагмент кода:
list<unsigned long> a_list;

unsigned long get_next()
{
	unsigned long ret = 0;
	if (!a_list.empty()) {
		ret = a_list.front();
		a_list.pop_front();
	}
	return ret;
}

VS2010: ничего
PVS-Studio: ничего

На первый взгляд все нормально, если не подумать, что может возникнуть гонка. Она — гонка (race condition) — может возникнуть, когда есть две программы, выполняемые в разных процессах или потоках. Эти программы могут прерывать друг друга, и при этом каждая изменяет один и тот же ресурс. В примере выше достаточно, чтобы один поток закончил проверку наличия элементов в списке, перед тем как другой извлечет из списка последний элемент с помощью вызова pop_front.

Вот, думаю для первого дубля достаточно, в следующем дубле планируется прогонять реальный тест, большое такое приложение. Хочу заметить, что как заметил idemura, не следует полагаться на анализаторы, скорее нужно просто повысить свой уровень профессионализма.

P. S. За грамматические ошибки… — писал пост поздно.
Tags: статический анализ кодаpvs-studioc++
Hubs: Designing and refactoring
Total votes 92: ↑49 and ↓43 +6
Comments 48
Comments Comments 48

Popular right now