2009-11-04 21 views
5

Je suis dans une situation où je suis obligé de faire au moins quelques efforts pour supprimer le code jamais utilisé de mon code source. La préférence générale est d'utiliser un outil d'analyse de code statique. Nous avons eu beaucoup de chance avec cela dans d'autres projets, mais les gens que j'entends sont pour la plupart des développeurs C/C++ travaillant sur le code au niveau de l'appareil. Je suis un développeur web travaillant sur un système Java EE. L'outil privilégié pour l'analyse est Coverity Prevent, bien que je pourrais probablement plaider pour quelque chose d'autre si je pouvais faire valoir que c'était plus approprié à la technologie que nous développons avec.Dans quelle mesure l'analyse de code statique fonctionne-t-elle avec Spring et d'autres abstractions?

Je me trouve douteux - quelle est l'effectivité de l'analyse de code statique pour le code mort, lorsque vous utilisez un système avec beaucoup d'abstractions? Par exemple, nous utilisons l'injection de dépendance de Spring, ainsi que JSF. Dans les deux cas, il n'y a pas de moyen facile de suivre les appels de fonctions du début à la fin et de faire une image complète de ce qui est appelé et de ce qui ne l'est pas.

Je suis très préoccupé par le fait que les faux positifs sur une vérification de code mort l'emporteront sur la valeur de l'exécution de l'outil en premier lieu.

Quelle est l'expérience de ce scénario? Avez-vous réussi à obtenir de la valeur à partir d'un outil d'analyse de code statique lorsque votre architecture utilisait beaucoup d'abstractions? Y avait-il quelque chose que vous deviez faire pour le faire fonctionner avec un minimum de faux positifs?

+0

Cela ressemble plus à une question de type wiki communautaire. –

Répondre

4

J'ai précédemment travaillé chez Coverity, sur le produit d'analyse statique Java.

Cette tâche particulière de trouver le code mort peut être hit-or-miss pour un analyseur statique. Pour les méthodes mortes en particulier, c'est-à-dire une méthode qui ne peut pas être appelée au moment de l'exécution, le taux de faux positifs sera très élevé sans beaucoup d'accord de votre part pour informer l'analyseur statique de tous les points d'entrée dynamiques. Pour un code à l'intérieur d'une méthode, si votre analyseur a cette capacité, les résultats devraient être assez bons, car l'analyse ne fera aucune hypothèse sur les données d'entrée. Même en supposant toutes les entrées possibe, il est possible de trouver le code mort où la logique corrélée empêche certaines branches d'être prises.

0

Dans tous les cas, l'analyse de code statique ne doit être effectuée que si vous comprenez parfaitement le processus d'analyse et le code. Le problème est simplement que c'est juste approximatif et offre des hypothèses. Ni une solution, ni un contrôle complètement précis des vulnérabilités. Vous devez pouvoir déterminer les faux positifs avec d'autres méthodes de test.

La valeur d'un analyseur de code statique n'est pas une révision de code. Pour éliminer le code mort, j'utiliserais la couverture de code pour le profiler. - Dans votre cas - vous avez mentionné beaucoup d'abstractions ... Je pense que l'analyse de code statique ne suffira pas.

+1

Cela semble être un conseil extrêmement strict. Donc, personne ne devrait utiliser Findbugs à moins de comprendre les limites d'une analyse de flux de données? Le produit de Coverity est hors limites jusqu'à ce que vous ayez lu les détails de l'interprétation abstraite? Si vous aimez les résultats, allez avec. Il n'y a pas besoin de comprendre exactement comment l'analyse est faite. –

+0

Mais c'est exactement ce que je voulais dire: personne ne devrait utiliser FindBugs, PMD ou tout ce qui concerne l'analyse de code statique, à moins qu'il/elle ne soit familier avec l'analyse de flux de données. Sinon, les gens ont tendance à essayer d'éviter la détection, mais produisent quand même les mêmes bugs. Seuls les programmeurs très sophistiqués peuvent utiliser efficacement l'analyse de code statique pour éliminer les vulnérabilités dans le code. Le produit qui trouve le problème n'écrit pas de correctif et ne connaît pas le modèle. – wishi

2

Vous pouvez utiliser des outils de couverture de test (analyse dynamique) pour déterminer quel code de votre système est utilisé; le complément est un code qui peut être mort (il n'a pas été exécuté!) et nécessite une inspection (par exemple, il peut y avoir des faux positifs). Plus vous donnez d'exercice à votre système, plus le taux de faux positifs est bas.

Un outil de couverture de test Java pouvant collecter ces données pour vous est disponible here.

Si vous souhaitez minimiser les faux positifs, vous pouvez envisager d'exécuter l'outil d'analyse statique et de tester la couverture, puis de prendre l'intersection.

En général, la détection du code mort X nécessite de prouver qu'il n'y a pas de conditions dans lesquelles X est invoqué. C'est difficile (théoriquement impossible) face à une machine de Turing et les instructions IF du formulaire

if (Turing(..)) then call X(); 

ce qui explique pourquoi les outils d'analyse statiques ont des taux élevé de faux positifs pour cela.

Dans de nombreux cas, cependant, le «code mort» est vraiment du code qui n'a tout simplement aucun moyen de l'invoquer («code réactif» dans le langage FAA). C'est-à-dire que, tandis que X est défini, il n'y a simplement aucune invocation de X (ou d'accès, si X est un élément de données) n'importe où dans le système, directement ou indirectement. Il est plus facile pour les outils d'analyse statique de détecter avec la complication désordonnée en Java du chargement et de la réflexion dynamique des classes (ce qui rend le problème de l'analyse de code désactive impossible face à des classes inconnues mais chargeables).

En ignorant ces complications, on peut trouver des outils d'analyse statiques qui détectent le code réactif dans les grands systèmes Java et le signalent. Un tel outil doit traiter tout le système Java en même temps car sinon une référence pourrait exister dans un module non inclus dans l'analyse. Nous avons construit un "deactive" code detector and remover peut même vous fournir votre code source avec tout le code désactivé automatiquement, ainsi que de signaler ce qui n'est pas référencé. Vous inspectez le rapport et décidez si vous souhaitez utiliser le code nettoyé ou ajouter un accès à une entité apparemment inutilisée.

+0

Les théories d'impossibilité sur les programmes sont surmontées quand il s'agit d'outils d'analyse statique. Le problème d'arrêt est un gros problème, comme référencé par votre méthode Turing(), mais il s'applique à l'optimisation des compilateurs, et personne ne doute de l'utilité d'un compilateur d'optimisation. Les outils d'analyse doivent fournir des preuves à l'utilisateur, et les utilisateurs ne croiront pas une chaîne de preuves complexe. Cela laisse le monde relativement banal, mais c'est intéressant car un outil peut trouver des problèmes qui sont très disparates dans le code de base, ce serait très difficile à identifier pour un humain, mais il est assez facile à vérifier pour un humain. –

+0

Je ne blâme pas les outils d'analyse statiques (je les écrase aussi!), Observant simplement que les théorisations ne garantissent pas la bonne réponse dans toutes les circonstances. Je suis d'accord que la bonne réponse est d'utiliser les outils d'analyse statique, car ils sont beaucoup mieux à gérer la complexité que les gens, mais de vérifier les réponses. "Faites confiance, mais vérifiez". –

1

En travaillant sur l'analyse statique, je ne connais aucun outil d'analyse statique qui fonctionne réellement avec des abstractions. Vous devrez probablement écrire un module qui s'intègre dans le processus d'analyse et les raisons de la façon dont vous utilisez les abstractions.

Et je doute que la présence de code mort coûte plus cher que cela.