PVS Studio.VS. Analyse statistique de GCC 10. Mini-test indépendant

Après la parution de l'article traduit sur l' analyse statique dans GCC 10 , et la réaction attendue des représentants du développeur de l'analyseur statique commercial PVS-Studio qui sont ici, j'ai demandé: «Pourquoi les représentants refusent-ils de tester leur produit avec des exemples aussi simples d'analyse statique, et ne se cachent-ils pas que sont-ils? "
Andrey2008Oui, ça ne m'intéresse pas. Pris / n'a pas attrapé une erreur synthétique, cela ne dit rien sur les capacités de l'analyseur
Devraient-ils en quelque sorte exécuter les tests unitaires de leur produit et comment, sinon avec de tels exemples synthétiques simples?!

En fait, je devais le faire moi-mĂŞme.

Numéro de test 1. L'exemple le plus simple d'une erreur double-free


Diagnostiqué avec:
V586 La fonction «libre» est appelée deux fois pour la désallocation du même espace mémoire. Inspectez le premier argument. Vérifiez les lignes: 5, 6. 1_dbl_free.c 6

RĂ©ussite au test

Numéro d'essai 2. longjmp () par free ()


Jurer incompréhensible à une constante dans malloc, mais une erreur a été détectée - code inaccessible et mémoire inutilisée: la
fonction malloc () V118 accepte une expression dangereuse en tant qu'argument. 2_longjump.c 13
V779 Code inaccessible détecté. Il est possible qu'une erreur soit présente. 2_longjump.c 15
V799 La variable 'ptr' n'est pas utilisée une fois que la mémoire lui a été allouée. Pensez à vérifier l'utilisation de cette variable. 2_longjump.c 13

décès

Numéro d'essai 3. Malloc () fuit et fopen () fichiers non fermés


Trouvé: La
fonction malloc () V118 accepte une expression dangereuse en tant qu'argument. 3_fopen.c 7
V773 La portée de visibilité du descripteur de fichier 'f' a été fermée sans fermer le fichier. Une fuite de ressources est possible. 3_fopen.c 9
V773 La portée de visibilité du pointeur 'p' a été quittée sans libérer la mémoire. Une fuite de mémoire est possible. 3_fopen.c 9
V799 La variable 'p' n'est pas utilisée une fois que la mémoire lui a été allouée. Pensez à vérifier l'utilisation de cette variable. 3_fopen.c 7

décès

Numéro de test 4. Surveillance de l'utilisation de la mémoire après l'avoir libérée


Bug détecté:
V774 Le pointeur 'n' a été utilisé après la libération de la mémoire. 4_use_after_free.c 9
V591 La fonction non-void doit renvoyer une valeur. 4_use_after_free.c 11

décès

Numéro d'essai 5. Contrôle de libération de pointeur non-tas (tas)


Des avertissements sans erreur ont été émis:
V104 Conversion implicite de 'n' au type memsize dans une expression arithmétique: sizeof (int) * n 5_free_nonheap.c 11
V799 La variable 'ptr' n'est pas utilisée une fois que la mémoire lui a été allouée. Pensez à vérifier l'utilisation de cette variable. 5_free_nonheap.c 11 a

échoué

Numéro de test 6. Gestionnaire d'appel interne () non valide


Échec

Bien que ce diagnostic soit si spécifique que je ne le lui reprocherais pas.

Ensuite, j'ai parcouru la liste des diagnostics dans GCC 10 et ajouté des exemples, donc d'autres tests avec des codes source.

Numéro de test 7. Double fermeture d'un fichier et libération d'un FICHIER fermé *


PVS n'a pas détecté ces erreurs.
GCC 10 a détecté une double fermeture mais n'a pas détecté la présence d'une poignée fermée.

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

Échoué

Numéro de test 8. longjmp () sur une pile obsolète


PVS n'a rien remarqué, le GCC10 a fonctionné correctement

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

Échoué

Numéro de test 9. Retourne le pointeur sur la variable de pile


Échec des deux participants, bien que dans des cas simples, GCC le détecte, mais ce n'est pas la fonction -fanalyzer (ou elle n'est peut-être pas encore implémentée).

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

Échoué

Numéro d'essai 10. Index de tableau contaminé et diagnostics d'utilisation de valeur non initialisée


Il semble qu'ils ne fonctionnent pas encore dans le fanalyzer GCC10 .

PVS attrape cela, comme cela a été démontré à plusieurs reprises.

RĂ©ussi

Conclusion


Il y a certainement une analyse statique dans PVS-Studio.

Bien qu'il ne soit pas sans inconvénients, il vaut la peine de l'utiliser, d'autant plus que de nombreuses erreurs humaines seront détectées, non seulement dans le domaine de l'analyse statique.

All Articles