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 6Réussite au testNumé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: lafonction malloc () V118 accepte une expression dangereuse en tant qu'argument. 2_longjump.c 13V779 Code inaccessible détecté. Il est possible qu'une erreur soit présente. 2_longjump.c 15V799 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 13décèsNuméro d'essai 3. Malloc () fuit et fopen () fichiers non fermés
Trouvé: Lafonction malloc () V118 accepte une expression dangereuse en tant qu'argument. 3_fopen.c 7V773 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 9V773 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 9V799 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 7décèsNumé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 9V591 La fonction non-void doit renvoyer une valeur. 4_use_after_free.c 11décèsNumé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 11V799 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
ÉchecBien 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);
closefile(f);
fclose(f);
free (p);
free(f);
}
É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éussiConclusion
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.