PVS Studio.VS. Análise estatística do GCC 10. Mini-teste independente

Após o surgimento do artigo traduzido sobre análise estática no GCC 10 e a reação esperada dos representantes do desenvolvedor do analisador estático comercial PVS-Studio que estão aqui, perguntei: “Por que os representantes se recusam a testar seu produto com exemplos tão simples para análise estática e não se escondem o que eles são? "
Andrey2008Sim, não é interessante para mim. Capturado / não detectou um erro sintético, isso não diz nada sobre os recursos do analisador
Deveriam, de alguma forma, executar os testes de unidade de seu produto e como, se não com exemplos simples e sintéticos ?!

Na verdade, eu tinha que fazer isso sozinho.

Teste número 1. O exemplo mais simples de erro duplo-livre


Diagnosticado com:
V586 A função 'livre' é chamada duas vezes para desalocação do mesmo espaço de memória. Inspecione o primeiro argumento. Verifique as linhas: 5, 6. 1_dbl_free.c 6

passou

Teste número 2. longjmp () por free ()


Palavrões incompreensíveis a uma constante no malloc, mas um erro foi detectado - código inacessível e memória não utilizada: a
função malloc () da V118 aceita uma expressão perigosa na capacidade de um argumento. 2_longjump.c 13
V779 Código inacessível detectado. É possível que haja um erro. 2_longjump.c 15
V799 A variável 'ptr' não é usada depois que a memória foi alocada para ela. Considere verificar o uso dessa variável. 2_longjump.c 13

aprovados

Teste número 3. Vazamentos de malloc () e arquivos não fechados fopen ()


Encontrado: A
função malloc () da V118 aceita uma expressão perigosa na capacidade de um argumento. 3_fopen.c 7
V773 O escopo de visibilidade do identificador de arquivo 'f' foi encerrado sem fechar o arquivo. Um vazamento de recurso é possível. 3_fopen.c 9
V773 O escopo de visibilidade do ponteiro 'p' foi encerrado sem liberar a memória. É possível um vazamento de memória. 3_fopen.c 9
V799 A variável 'p' não é usada após a alocação de memória para ela. Considere verificar o uso dessa variável. 3_fopen.c 7

aprovados

Teste número 4. Monitorando o uso da memória após liberá-lo


Bug Detectado:
V774 O ponteiro 'n' foi usado após o lançamento da memória. 4_use_after_free.c 9
V591 A função não nula deve retornar um valor. 4_use_after_free.c 11

aprovados

Teste número 5. Controle de liberação de ponteiro sem heap (heap)


Avisos de não erro foram emitidos:
V104 Conversão implícita de 'n' para tipo memsize em uma expressão aritmética: sizeof (int) * n 5_free_nonheap.c 11
V799 A variável 'ptr' não é usada depois que a memória foi alocada para ele. Considere verificar o uso dessa variável. 5_free_nonheap.c 11

falhou

Teste número 6. Manipulador de sinal interno () de chamada inválido


Falhou

Embora este seja um diagnóstico tão específico que eu não o reprovaria.

Em seguida, examinei a lista de diagnósticos no GCC 10 e adicionei exemplos, para mais testes com códigos-fonte.

Teste número 7. Fechando um arquivo duas vezes e liberando um arquivo fechado *


O PVS não detectou esses erros O
GCC 10 detectou fechamento duplo, mas não detectou livre para um identificador fechado.

#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
}

Falhou

Teste número 8. longjmp () em uma pilha obsoleta


PVS não notou nada, GCC10 funcionou corretamente

#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();
}

Falhou

Teste número 9. Retorne o ponteiro para empilhar a variável


Falha em ambos os participantes, embora em casos simples, o GCC detecte isso, mas essa não é a função -fanalyzer (ou talvez ainda não esteja implementada).

#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;
}

Falhou

Teste número 10. Diagnóstico de índice de matriz corrompida e uso de valor não inicializado


Parece que eles ainda não estão funcionando no ventilador do GCC10 .

O PVS captura isso, como foi demonstrado muitas vezes.

Passado

Conclusão


Definitivamente, existe uma análise estática no PVS-Studio.

Embora não sem alguns inconvenientes, vale a pena usá-lo, especialmente porque muitos erros humanos serão detectados, não apenas no campo da análise estática.

All Articles