Salutations à tous les amoureux des insectes. La nouvelle année arrive bientôt, il est donc temps de faire le point sur l'année qui s'en va. Par tradition, un classement des erreurs les plus intéressantes découvertes par l'équipe PVS-Studio dans les projets ouverts C # pour 2019. Êtes-vous prêt? Commençons alors.
Dixième place: «confondre tout le monde»
V3066 Ordre incorrect possible des arguments passés à la méthode 'AdjustCellBorderStyle': 'isFirstDisplayedRow' et 'isFirstDisplayedColumn'. DataGridViewComboBoxCell.cs 1934
protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { .... dgvabsEffective = AdjustCellBorderStyle( DataGridView.AdvancedCellBorderStyle, dgvabsPlaceholder, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedRow,
Erreur de l'article "
WinForms: Erreurs, Holmes ". L'analyseur indique que lors du passage d'arguments à la méthode, les deux derniers arguments ont été inversés. Jetez un œil à la
déclaration AdjustCellBorderStyle :
public virtual DataGridViewAdvancedBorderStyle AdjustCellBorderStyle( DataGridViewAdvancedBorderStyledataGridViewAdvancedBorderStyleInput, DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { .... }
Il semble que l'analyseur ait raison. Souvent, certains arguments sont délibérément passés dans l'ordre inverse, par exemple, afin d'échanger certaines variables. Mais il ne semble pas que ce soit exactement le cas. Tout d'abord, les variables de type
booléen sont confuses. Deuxièmement, les noms des méthodes sont également courants: pas de «Swap» ou «Reverse». De plus, il n'est pas si difficile de se tromper comme ceci: les gens perçoivent souvent différemment l'ordre de la paire ligne / colonne.
Neuvième place: "L'Infini est proche"
V3110 Récursion infinie possible dans la méthode 'TryValidateModel'. PrefixedModuleUpdater.cs 48
public bool TryValidateModel(object model, string prefix) { return TryValidateModel(model, Prefix(prefix)); }
Erreur de l'article "
Recherche et analyse des erreurs dans le code Orchard CMS ". Une erreur a été commise qui provoque une récursion infinie. Pour comprendre comment cette erreur a pu être commise, vous devez examiner la surcharge de la méthode
TryValidateModel :
public bool TryValidateModel(object model) { return _updateModel.TryValidateModel(model); }
Il est probable que dans le premier cas un appel du formulaire soit utilisé:
public bool TryValidateModel(object model, string prefix) { return _updateModel.TryValidateModel(model, Prefix(prefix)); }
Le code compilé car
_updateModel est de type
IUpdateModel et la classe actuelle implémente également l'interface
IUpdateModel .
Huitième place: «Essayez, trouvez»
V3091 Analyse empirique. Il est possible qu'une faute de frappe soit présente à l'intérieur du littéral de chaîne: "ID du groupe de gestion". Le mot «Id» est suspect. Constants.cs 36
public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id";
L'erreur provient de l'article «
Azure PowerShell:« fondamentalement inoffensif ». L'analyseur soupçonne que la constante
GroupName a été initialisée avec une chaîne d'erreur. Il devrait probablement y avoir quelque chose comme
« Management Group Name » . Il est difficile de juger de la criticité de cette erreur, mais elle est particulièrement rare et difficile à détecter.
Septième place: "Juste négligé"
V3078 L'ordre de tri d'origine sera perdu après un appel répétitif à la méthode 'OrderBy'. Utilisez la méthode 'ThenBy' pour conserver le tri d'origine. GridModel.Selection.cs 107
internal partial class GridModel { private void BuildCellSelectionRegions(....) { .... this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .OrderBy(c => c.RowItemInfo.LayoutInfo.Line)); } }
Erreur de l'article "
Vérification de l'interface utilisateur de Telerik pour UWP pour se familiariser avec PVS-Studio ". En raison de la réutilisation de
OrderBy pour une collection déjà triée, le résultat du tri précédent sera perdu. Vous devez utiliser
ThenBy :
this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line));
De telles erreurs sont commises par négligence ou par ignorance. Je pense que le copier-coller est à blâmer.
Sixième place: «Le code est documenté», ont-ils déclaré
V3009 Il est étrange que cette méthode renvoie toujours une seule et même valeur de 'true'. MaskedTextProvider.cs 1529
public bool Remove(out int testPosition, out MaskedTextResultHint resultHint) { .... if (lastAssignedPos == INVALID_INDEX) { .... return true;
Erreur de l'article "
Vérification du code source des bibliothèques .NET Core avec l'analyseur statique PVS-Studio ". La méthode retournera toujours
true . Oui, c'est une erreur, mais quelque chose d'autre est curieux. Un commentaire détaillé est joint à la méthode:
Supprime le dernier caractère de la chaîne formatée. (Supprimer le dernier caractère de la chaîne virtuelle). A la sortie, le paramètre out contient la position où l'opération a été réellement effectuée. Cette position est relative à la chaîne de test. Le paramètre MaskedTextResultHint out donne plus d'informations sur le résultat de l'opération. Renvoie vrai en cas de succès, faux sinon.Concentrez-vous sur la dernière phrase. Mais qui a jamais lu ces commentaires? Mais sérieusement, une telle erreur se glisse facilement, par exemple, lors de la refactorisation ou du débogage. Nous voulions vérifier l'option lorsque le résultat de la méthode sera toujours
vrai , eh bien, nous avons oublié de tout renvoyer tel qu'il était.
Cinquième place: "Indexez-moi, immédiatement!"
V3102 Accès suspect à l'élément de l'objet 'seq' par un index constant à l'intérieur d'une boucle. XmlQueryRuntime.cs 738
public bool MatchesXmlType(IList<XPathItem> seq, ....) { .... for (int i = 0; i < seq.Count; i++) { if (!CreateXmlType(seq[0]).IsSubtypeOf(....)) return false; } return true; }
Erreur de l'article "
Vérification du code source des bibliothèques .NET Core avec l'analyseur statique PVS-Studio ". Lors de la traversée de la collection
seq , la boucle
for utilise par erreur uniquement l'accès à son premier élément à toutes les itérations (index 0 au lieu de
i ).
Quatrième place: «Juste un dollar et pas assez»
V3138 Le littéral de chaîne contient une expression interpolée potentielle. Envisagez d'inspecter: e. SSPIHandleCache.cs 42
internal static void CacheCredential(SafeFreeCredentials newHandle) { try { .... } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { NetEventSource.Fail(null, "Attempted to throw: {e}"); } } }
Erreur de l'article "
Vérification du code source des bibliothèques .NET Core avec l'analyseur statique PVS-Studio ". La chaîne
«Tentative to throw: {e}» semble être interpolée. En raison du caractère
$ manquant, la représentation sous forme de chaîne de l'exception
e ne sera pas remplacée dans la chaîne. Par conséquent, la chaîne sera utilisée «telle quelle».
Troisième place: "Il n'y a pas d'issue"
V3008 [CWE-563] La variable 'this.linker.s3.region' reçoit des valeurs successives deux fois. C'est peut-être une erreur. Vérifiez les lignes: 116, 114. AWSSDK.DynamoDBv2.Net45 S3Link.cs 116
public string Region { get { .... } set { if (String.IsNullOrEmpty(value)) { this.linker.s3.region = "us-east-1"; } this.linker.s3.region = value; } }
Erreur de l'article «
Recherche d'erreurs dans le code source du SDK Amazon Web Services pour .NET ». Dans le corps du bloc
if , le
retour a été ignoré. Par conséquent, la variable
this.linker.s3.region obtiendra toujours une
valeur , y compris une chaîne vide et
null .
Deuxième place: "Devenez en ordre!"
V3070 La variable non initialisée 'LANG_USER_DEFAULT' est utilisée lors de l'initialisation de la variable 'LOCALE_USER_DEFAULT'. NativeMethods.cs 890
internal static class NativeMethods { .... public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); .... }
Erreur de l'article "
WinForms: Erreurs, Holmes ". L'ordre d'initialisation des champs de classe est mélangé. Pour calculer la valeur du champ
LOCALE_USER_DEFAULT , utilisez le champ
LANG_USER_DEFAULT , qui n'est pas encore initialisé et a une valeur de 0. La variable
LANG_USER_DEFAULT n'est utilisée nulle part ailleurs dans le code. Pour comprendre à quoi cette erreur conduit, un programme de test a été écrit contenant des méthodes du code WinForms. Par souci de simplicité, certaines constantes réelles ont été remplacées par leurs valeurs réelles:
internal static class NativeMethods { public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(0x00, 0x01); public static int MAKELANGID(int primary, int sub) { return ((((ushort)(sub)) << 10) | (ushort)(primary)); } public static int MAKELCID(int lgid) { return MAKELCID(lgid, 0x0); } public static int MAKELCID(int lgid, int sort) { return ((0xFFFF & lgid) | (((0x000f) & sort) << 16)); } } class Program { static void Main() { System.Console.WriteLine(NativeMethods.LOCALE_USER_DEFAULT); } }
À la suite du lancement, les éléments suivants seront affichés sur la console: 0. Nous allons maintenant corriger l'erreur en échangeant la déclaration des
champs LOCALE_USER_DEFAULT et
LANG_USER_DEFAULT . Le résultat du programme sous cette forme: 1024.
Première place: "Faites confiance, mais vérifiez"
La première place est toujours difficile. Il doit y avoir quelque chose d'extraordinaire et de très intéressant. Au départ, j'ai sélectionné plus de vingt erreurs intéressantes pour cet article, mais il n'y avait rien de digne de leur première place. Et puis je me suis souvenu d'un article de mon collègue Sergey Vasiliev, consacré à une seule erreur. La beauté de cette erreur est qu'elle a directement affecté le fonctionnement de notre analyseur. Comment? Cela ressort déjà du titre de l'article "
Historique de la façon dont PVS-Studio a trouvé une erreur dans la bibliothèque utilisée dans ... PVS-Studio ". Encore une fois, la paresse n'a pas été annulée. :) Et là, j'ai complètement honte et je ne donnerai pas de description de l'erreur, mais je proposerai de suivre le lien vers l'article et d'en savoir plus. Je le garantis - ça vaut le coup. Et l'article est court.
Conclusion
J'espère que les erreurs ont été intéressantes, mais l'article ne s'est pas fatigué. Je vous rappelle que vous pouvez toujours
télécharger l' analyseur PVS-Studio pour rechercher vous-même les erreurs dans vos propres projets et ceux de tiers, pour vous faire plaisir, amis et collègues. Et qu'il y ait moins d'erreurs et plus de temps pour s'améliorer! :)
As-tu lu? Félicitations pour le passage au niveau suivant! Dans les articles suivants de notre blog, les meilleurs bugs de 2019 dans
les projets
Java et
C ++ sont mis en évidence .

Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien vers la traduction: Sergey Khrenov.
Top 10 des bugs trouvés dans les projets C # en 2019 .