17 апреля

PVS Studio.VS.Статический анализ GCC 10. Независимый минитест

CПромышленное программирование
После появления переводной статьи про Статический анализ в GCC 10, и ожидаемой реакции присутствующих здесь представителей разработчика коммерческого статического анализатора PVS-Studio, у меня возник вопрос: «Почему же представители отказываются проверить свой продукт на таких простых примерах для статического анализа, и не скрывают ли они чего?»
Andrey2008 Ды, неинтересно мне это. Поймал/не поймал синтетическую ошибку, это ничего не говорит о возможностях анализатора
Должны же они как то прогонять юнит-тесты своего продукта и как, если не на таких синтетических простых примерах?!

Собственно, пришлось сделать это самому.

Тест №1. Самый простой пример ошибки double-free


Обнаружена с диагностикой:
V586 The 'free' function is called twice for deallocation of the same memory space. Inspect the first argument. Check lines: 5, 6. 1_dbl_free.c 6

Пройден

Тест №2. longjmp() мимо free()


Непонятная ругань на константу в malloc, но ошибка обнаружена — недоступный код и неиспользованная память:
V118 malloc() function accepts a dangerous expression in the capacity of an argument. 2_longjump.c 13
V779 Unreachable code detected. It is possible that an error is present. 2_longjump.c 15
V799 The 'ptr' variable is not used after memory has been allocated for it. Consider checking the use of this variable. 2_longjump.c 13

Пройден

Тест №3. Утечки malloc() и незакрытые файлы fopen()


Обнаружены:
V118 malloc() function accepts a dangerous expression in the capacity of an argument. 3_fopen.c 7
V773 Visibility scope of the 'f' file handle was exited without closing the file. A resource leak is possible. 3_fopen.c 9
V773 Visibility scope of the 'p' pointer was exited without releasing the memory. A memory leak is possible. 3_fopen.c 9
V799 The 'p' variable is not used after memory has been allocated for it. Consider checking the use of this variable. 3_fopen.c 7

Пройден

Тест №4. Контроль использования памяти после ее освобождения


Баг обнаружен:
V774 The 'n' pointer was used after the memory was released. 4_use_after_free.c 9
V591 Non-void function should return a value. 4_use_after_free.c 11

Пройден

Тест №5. Контроль освобождения указателя не на кучу (heap)


Выданы предупреждения, не относящиеся к ошибке:
V104 Implicit conversion of 'n' to memsize type in an arithmetic expression: sizeof (int) * n 5_free_nonheap.c 11
V799 The 'ptr' variable is not used after memory has been allocated for it. Consider checking the use of this variable. 5_free_nonheap.c 11

Провален

Тест №6. Недопустимый вызов внутри обработчика signal()


Провален

Хотя это настолько специфическая диагностика, что я бы не ставил ее в укор.

Далее я прошелся по перечню диагностик в GCC 10 и дописал примеры, потому дальнейшие тесты с исходниками.

Тест №7. Двойное закрытие файла и освобождение закрытого FILE*


PVS не обнаружил этих ошибок
GCC 10 обнаружил double-fclose но не обнаружил free для закрытого хендла.

#include <stdlib.h>
void closefile(FILE* f) {
	fclose(f);
}

void test(const char *filename) {
  FILE *f = fopen(filename, "r");
  void *p = malloc(1024);
  /* do stuff */
  closefile(f);
  fclose(f);
  free (p);
  free(f);  // <-  UB
}

Провален

Тест №8. longjmp() на устаревший стек


PVS не заметил ничего, GCC10 отработал верно

#include <setjmp.h>
#include <stdlib.h>
static jmp_buf env;
static int i;

static void inner(void) {
  longjmp(env, 1);
}

static void middle(void) {
  inner();
}

void outer(void) {
  i = setjmp(env);
}

void outer_x2(void) {
  outer();
  if (i == 0)
    middle();
}

Провален

Тест №9. Возврат указателя на стековую переменную


Провален обоими участниками, хотя в простых случаях GCC обнаруживает такое, но это еще не функция -fanalyzer (а может еще не реализована).

#include<stdlib.h>

struct str1 {
    char buf[10];
};

struct str1 * ret(int sel)
{
    struct str1  var1, *pval;

    if(sel == 1)
        pval = &var1;
    else if(sel != 1)
        pval = (struct str1 *)malloc(1000);

    return pval;
}

Провален

Тест №10. Диагностики tainted-array-index и use-of-uninitialized-value


Похоже, еще не работают в GCC10 -fanalyzer.

PVS такое отлавливает, как много раз уже демонстрировалось.

Пройден

Вывод


Статический анализ в PVS-Studio определенно есть.

Хотя и не без некоторых недостатков, но и им стоит пользоваться, тем более, что будут обнаружены и многие человеческие ошибки, не только из области статического анализа.
Теги:cpvsstatic code analysis
Хабы: C Промышленное программирование
+29
4,7k 20
Комментарии 15
Похожие публикации
C/C++ Developer, Digital image processing
от 2 000 до 2 500 $Almalence, Inc.Новосибирск
Software Developer for Remote Collaborative Tool (‘Code With Me’)
от 200 000 ₽JetBrainsСанкт-Петербург
Senior Software Engineer - Swift
от 3 000 до 4 500 $UscreenМожно удаленно
Reverse Engineer
от 3 000 до 4 000 $Hand2NoteМожно удаленно
Программист BIOS
от 160 000 ₽AquariusМосква
Лучшие публикации за сутки