Il s'agit d'une courte histoire sur la façon dont l'utilisation de PVS-Studio a permis de trouver une erreur dans le code source de la bibliothèque utilisée dans PVS-Studio. De plus, non théorique, mais réelle - l'erreur s'est manifestée dans la pratique lors de l'utilisation de la bibliothèque dans l'analyseur.
Dans PVS-Studio_Cmd (ainsi que certains autres utilitaires), nous utilisons une bibliothèque spéciale pour analyser les arguments de ligne de commande - CommandLine.
Aujourd'hui, j'étais engagé dans la prise en charge du nouveau mode dans PVS-Studio_Cmd, et il se trouve que j'ai dû utiliser cette bibliothèque d'arguments d'analyse. En train d'écrire du code, je le débogue également, car je dois travailler avec des API inconnues.
Ainsi, le code est écrit, compilé, exécuté pour exécution, ii ...
L'exécution du code passe dans la bibliothèque où se produit une exception de type
NullReferenceException . D'un côté, ce n'est pas très clair - je ne transmets aucune référence nulle explicite à la méthode.
Au cas où, je regarde les commentaires sur la méthode appelée. Il est très peu probable qu'ils décrivent les conditions d'une exception de type
NullReferenceException (car généralement, comme il me semble, les exceptions de ce type sont imprévues).
Dans les commentaires sur la méthode, il n'y a aucune information sur une
NullReferenceException (qui, cependant, est attendue).
Afin de voir ce qui cause exactement l'exception (et où), j'ai décidé de télécharger le code source du projet, de compiler et de connecter la version de débogage de la bibliothèque à l'analyseur. Le code source du projet
est disponible sur GitHub . La version 1.9.71 est requise, car c'est précisément ce type qui est maintenant utilisé dans l'analyseur.
Je charge la version appropriée du code source, collecte, connecte la bibliothèque de débogage à l'analyseur, exécute le code pour exécution et vois:
Ainsi, la place de l'exception est claire -
helpInfo est
null , ce qui provoque une exception de type
NullReferenceException lors de l'accès à la propriété d'instance
Left .
Et puis je suis devenu pensif. Récemment, PVS-Studio pour C # a été assez bien amélioré dans divers domaines, y compris dans le domaine de la recherche de déréférencement de références potentiellement nulles. En particulier, l'analyse interprocédurale a été améliorée. Par conséquent, il est immédiatement devenu intéressant pour moi de vérifier le code source pour voir si PVS-Studio pouvait trouver l'erreur en cours de discussion.
J'ai vérifié le code source, et entre autres avertissements, j'ai vu exactement ce que j'espérais.
Avertissement PVS-Studio :
V3080 Déréférence nulle possible à l'intérieur de la méthode à 'helpInfo.Left'. Pensez à inspecter le deuxième argument: helpInfo. Parser.cs 405
Oui, ça y est! Exactement ce dont vous avez besoin. Examinons le code source plus en détail.
private bool DoParseArgumentsVerbs( string[] args, object options, ref object verbInstance) { var verbs = ReflectionHelper.RetrievePropertyList<VerbOptionAttribute>(options); var helpInfo = ReflectionHelper.RetrieveMethod<HelpVerbOptionAttribute>(options); if (args.Length == 0) { if (helpInfo != null || _settings.HelpWriter != null) { DisplayHelpVerbText(options, helpInfo, null);
L'analyseur génère un message d'avertissement lors de l'appel de la méthode
DisplayHelpVerbText et met en garde contre le deuxième argument -
helpInfo . Notez que cette méthode se trouve dans la branche
then de l'
instruction if . L'expression conditionnelle est composée de telle manière que
then- branch puisse être exécuté avec les valeurs de variables suivantes:
- helpInfo == null ;
- _settings.HelpWriter! = null ;
Voyons le corps de la méthode
DisplayHelpVerbText :
private void DisplayHelpVerbText( object options, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb) { string helpText; if (verb == null) { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, null, out helpText); } else { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, verb, out helpText); } if (_settings.HelpWriter != null) { _settings.HelpWriter.Write(helpText); } }
Depuis le
verbe == null (voir l'appel de méthode), nous nous intéressons à la branche
then- de l'
instruction if . Bien que la situation avec la branche
else soit similaire, nous considérerons la branche
then , puisque dans notre cas particulier l'exécution a été effectuée à travers elle. N'oubliez pas que
helpInfo peut être
nul .
Examinons maintenant le corps de la méthode
HelpVerbOptionAttribute.InvokeMethod . En fait, vous l'avez déjà vu dans la capture d'écran ci-dessus:
internal static void InvokeMethod( object target, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb, out string text) { text = null; var method = helpInfo.Left; if (!CheckMethodSignature(method)) { throw new MemberAccessException( SR.MemberAccessException_BadSignatureForHelpVerbOptionAttribute .FormatInvariant(method.Name)); } text = (string)method.Invoke(target, new object[] { verb }); }
helpInfo.Left est appelé sans condition, même si
helpInfo peut être
null . L'analyseur en a averti et cela s'est produit.
ConclusionIl s'est avéré drôle qu'avec l'aide de PVS-Studio, il était possible de trouver une erreur dans le code de la bibliothèque utilisée dans PVS-Studio. Je pense que c'est une sorte de suite de la réponse à la question "PVS-Studio trouve-t-il des erreurs dans le code PVS-Studio?". :) Il peut trouver des erreurs non seulement dans le code PVS-Studio, mais aussi dans le code des bibliothèques utilisées.
Enfin, je propose de
télécharger l'analyseur et d'essayer de vérifier votre projet - que faire si vous y trouvez aussi quelque chose d'intéressant?

Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien vers la traduction: Sergey Vasiliev.
L'histoire de la façon dont PVS-Studio a trouvé une erreur dans la bibliothèque utilisée dans ... PVS-Studio