Bonjour à tous. Aujourd'hui, nous avons un autre projet Microsoft sur le chèque. Par le titre de cet article, vous pouvez deviner que cette fois, les développeurs ne nous ont pas "plu" avec un grand nombre d'erreurs. Nous espérons que les auteurs du projet ne seront pas offensés par le titre. Après tout, un petit nombre d'erreurs, c'est bien, non? Cependant, nous avons quand même réussi à trouver quelque chose d'intrigant dans le code Azure PowerShell. Nous vous suggérons de vous familiariser avec les fonctionnalités de ce projet et de vérifier les erreurs trouvées à l'aide de l'analyseur PVS-Studio C #.
À propos du projet
Azure PowerShell est un ensemble de commandlets (
cmdlet ) qui vous permet de gérer les ressources
Azure directement à partir de la ligne de commande
PowerShell . L'objectif principal de cet ensemble est de simplifier le processus d'étude et de démarrer rapidement le développement pour Azure. Azure PowerShell fournit aux administrateurs et aux développeurs des fonctionnalités convaincantes pour créer, déployer et gérer des applications Microsoft Azure.
Azure PowerShell est développé dans l'environnement .NET Standard, est pris en charge par PowerShell 5.1 pour Windows et PowerShell 6.x et versions ultérieures pour toutes les plateformes. Le
code source Azure PowerShell est disponible sur GitHub.
Récemment, j'ai souvent reçu des projets Microsoft pour une vérification. À mon avis, la qualité de ces projets est généralement de premier ordre. Bien sûr, non sans exception, comme décrit dans l'article "
WinForms: Erreurs, Holmes ". Mais cette fois, tout va bien. Le projet est volumineux: les fichiers de code source de 6845 .cs contiennent environ 700 000 lignes, à l'exclusion des lignes vides (je n'ai pas pris en compte les tests et avertissements du troisième niveau de certitude). Très peu d'erreurs ont été trouvées pour une telle quantité de code: pas plus d'une centaine. Il y avait beaucoup de cas similaires, j'ai donc choisi les plus intéressants pour l'article. Comme d'habitude, j'ai trié les erreurs en fonction des numéros d'avertissement de PVS-Studio.
De plus, je suis tombé sur des fragments de code qui ressemblaient à des erreurs, mais ne pouvaient pas être reconnus comme définitivement erronés, car je ne suis pas assez familier avec les particularités de développement de PowerShell. J'espère que parmi les lecteurs, il y aura des spécialistes de ce numéro qui m'aideront. Je vais le décrire en détail ci-dessous.
Avant la partie feedback, je voudrais mentionner la structure spécifique du projet. Le code source Azure PowerShell comprend plus de soixante-dix solutions Visual Studio. Certaines solutions incluent des projets d'autres. Cette structure a un peu ralenti l'analyse (pas beaucoup). Mais le chèque n'a pas posé d'autres difficultés. Pour plus de commodité, dans le message d'erreur (entre parenthèses), je spécifierai le nom de la solution où l'erreur a été trouvée.
Résultats d'analyse
V3001 Il existe des sous-expressions identiques 'strTimespan.Contains ("M")' à gauche et à droite de '||' opérateur. AzureServiceBusCmdletBase.cs 187 (EventGrid)
public static TimeSpan ParseTimespan(string strTimespan) { .... if (strTimespan.Contains("P") || strTimespan.Contains("D") || strTimespan.Contains("T") || strTimespan.Contains("H") || strTimespan.Contains("M") || strTimespan.Contains("M")) .... }
Un exemple d'une erreur assez évidente que seul un développeur peut corriger. Dans ce cas, il est absolument difficile de savoir si nous traitons la duplication de code qui n'affecte rien ou autre chose doit avoir lieu au lieu de
"M" dans l'un des deux derniers contrôles.
V3001 Il existe des sous-expressions identiques 'this.AggregationType! = Null' à gauche et à droite de l'opérateur '&&'. GetAzureRmMetricCommand.cs 156 (moniteur)
public AggregationType? AggregationType { get; set; } .... protected override void ProcessRecordInternal() { .... string aggregation = (this.AggregationType != null && this.AggregationType.HasValue) ? this.AggregationType.Value.ToString() : null; .... }
Il n'y a probablement aucune erreur ici. Ceci est un exemple de code redondant. Parfois, un tel code peut indiquer un manque de connaissances du développeur. Le fait est que les vérifications
this.AggregationType! = Null et
this.AggregationType.HasValue sont identiques. Il suffit d'en utiliser un seul (n'importe lequel). Personnellement, je préfère l'option avec
HasValue: string aggregation = this.AggregationType.HasValue ? this.AggregationType.Value.ToString() : null;
V3003 L'utilisation du
modèle 'if (A) {...} else if (A) {...}' a été détectée. Il y a une probabilité de présence d'erreur logique. Vérifiez les lignes: 152, 163. GetAzureRmRecoveryServicesBackupProtectionPolicy.cs 152 (RecoveryServices)
public override void ExecuteCmdlet() { .... if( WorkloadType == Models.WorkloadType.AzureVM ) { .... } .... else if( WorkloadType == Models.WorkloadType.AzureFiles ) { if( BackupManagementType != Models.BackupManagementType.AzureStorage ) { throw new ArgumentException( Resources.AzureFileUnsupportedBackupManagementTypeException ); } serviceClientProviderType = ServiceClientHelpers. GetServiceClientProviderType( Models.WorkloadType.AzureFiles ); } else if( WorkloadType == Models.WorkloadType.AzureFiles ) { if( BackupManagementType != Models.BackupManagementType.AzureStorage ) { throw new ArgumentException( Resources.AzureFileUnsupportedBackupManagementTypeException ); } serviceClientProviderType = ServiceClientHelpers. GetServiceClientProviderType( Models.WorkloadType.AzureFiles ); } .... }
Deux
autres si les blocs sont absolument identiques, y compris la condition et le corps du bloc. De telles erreurs sont généralement commises lors de l'utilisation de la méthode copier-coller. Le problème ici est encore une fois la criticité de l'erreur. S'il ne s'agit pas d'une simple duplication de code, il peut s'agir de la vérification nécessaire absente et d'un ensemble approprié d'actions. L'auteur doit définitivement modifier le code.
V3005 La variable 'this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent' est affectée à elle-même. SetAzureVMOperatingSystemCommand.cs 298 (Calcul)
public override void ExecuteCmdlet() { ....
La valeur de la propriété est auto-assignée. Jetez un œil à sa déclaration:
[JsonProperty(PropertyName = "provisionVMAgent")] public bool? ProvisionVMAgent { get; set; }
La description de
JsonProperty indique: "Demande au Newtonsoft.Json.JsonSerializer de toujours sérialiser le membre avec le nom spécifié." Il semble que tout soit sans culpabilité et l'erreur évidente a été commise. L'utilisation explicite de
cela pour accéder à la propriété est également assez déroutante. Peut-être qu'une autre variable n'a pas été spécifiée par erreur à la place de
cela. Mais ne sautons pas aux conclusions. Le fait est que j'ai rencontré pas mal de ces affectations (une propriété est auto-assignée). Voici un exemple d'affectation, très similaire à une erreur:
V3005 La variable 'this.LastHeartbeat' est assignée à elle-même. PSFabricDetails.cs 804 (RecoveryServices)
public ASRInMageAzureV2SpecificRPIDetails( InMageAzureV2ReplicationDetails details) { this.LastHeartbeat = this.LastHeartbeat;
Examinons de plus près la deuxième affectation et les affectations suivantes. Dans la partie droite de l'expression, des
détails ont lieu à la place de
cela. Regardez maintenant la déclaration de la propriété
this.LastHeartbeat :
public DateTime? LastHeartbeat { get; set; }
Enfin, recherchons la propriété du même nom dans la classe
InMageAzureV2ReplicationDetails . Ces biens y sont déclarés:
public class InMageAzureV2ReplicationDetails : ReplicationProviderSpecificSettings { .... [JsonProperty(PropertyName = "lastHeartbeat")] public DateTime? LastHeartbeat { get; set; } .... }
Eh bien, dans ce cas, je suis prêt à admettre que c'est une véritable erreur. Mais que ferons-nous des prochains avertissements? Contrairement à deux fragments de code précédents, il existe plusieurs propriétés auto-attribuées. Eh bien, cela ressemble moins à une erreur:
- V3005 La variable 'this.ResourceGroupName' est assignée à elle-même. RemoveAzureRmExpressRouteConnectionCommand.cs 84 (CognitiveServices)
- V3005 La variable 'this.ExpressRouteGatewayName' est assignée à elle-même. RemoveAzureRmExpressRouteConnectionCommand.cs 85 (CognitiveServices)
- V3005 La variable 'this.Name' est assignée à elle-même. RemoveAzureRmExpressRouteConnectionCommand.cs 86 (CognitiveServices)
[Cmdlet(VerbsCommon.Remove, ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "ExpressRouteConnection", DefaultParameterSetName = CortexParameterSetNames.ByExpressRouteConnectionName, SupportsShouldProcess = true), OutputType(typeof(bool))] public class RemoveExpressRouteConnectionCommand : ExpressRouteConnectionBaseCmdlet { [Parameter( Mandatory = true, ParameterSetName = CortexParameterSetNames.ByExpressRouteConnectionName, HelpMessage = "The resource group name.")] [ResourceGroupCompleter] [ValidateNotNullOrEmpty] public string ResourceGroupName { get; set; } .... public override void Execute() { if (....) { this.ResourceGroupName = this.ResourceGroupName; this.ExpressRouteGatewayName = this.ExpressRouteGatewayName; this.Name = this.Name; } .... } .... }
La méthode
Execute contient les auto-affectations de trois propriétés consécutives. Au cas où, j'ai cité la déclaration complète de la classe
RemoveExpressRouteConnectionCommand et tous ses attributs, ainsi que la déclaration de propriété
ResourceGroupName (les deux autres propriétés sont déclarées de manière similaire). Ce sont ces avertissements qui m'ont fait réfléchir à la question: "Est-ce une erreur?" Je soupçonne qu'une certaine magie interne du développement PowerShell peut se produire ici. J'espère que parmi les lecteurs, il y aura des experts informés de cette question. Je ne suis pas prêt à tirer des conclusions dans ce cas.
V3006 L'objet a été créé mais il n'est pas utilisé. Le mot clé 'throw' peut être manquant: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 259 (RecoveryServices)
private void StartRPITestFailover() { .... if (....) { .... } else { new ArgumentException( Resources .UnsupportedDirectionForTFO);
Le mot clé
throw est omis. Et le commentaire dit que l'exception doit juste être levée. J'ai rencontré plusieurs erreurs similaires dans la solution
RecoveryServices :
- V3006 L'objet a été créé mais il n'est pas utilisé. Le mot clé 'throw' peut être manquant: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 305 (RecoveryServices)
- V3006 L'objet a été créé mais il n'est pas utilisé. Le mot clé 'throw' peut être manquant: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 278 (RecoveryServices)
- V3006 L'objet a été créé mais il n'est pas utilisé. Le mot clé 'throw' peut être manquant: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 322 (RecoveryServices)
- V3006 L'objet a été créé mais il n'est pas utilisé. Le mot clé 'throw' peut être manquant: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 421 (RecoveryServices)
- V3006 L'objet a été créé mais il n'est pas utilisé. Le mot clé 'throw' peut être manquant: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 452 (RecoveryServices)
V3022 L' expression 'apiType.HasValue' est toujours fausse. ApiManagementClient.cs 1134 (ApiManagement)
private string GetApiTypeForImport(...., PsApiManagementApiType? apiType) { .... if (apiType.HasValue) { switch(apiType.Value) { case PsApiManagementApiType.Http: return SoapApiType.SoapToRest; case PsApiManagementApiType.Soap: return SoapApiType.SoapPassThrough; default: return SoapApiType.SoapPassThrough; } } return apiType.HasValue ?
La logique du travail a été brisée. Si
apiType contient une valeur, le contrôle n'atteindra pas l'expression de
retour à la fin de la méthode (toutes les branches de
commutateur contiennent
return ). Sinon, la méthode renverra toujours
PsApiManagementApiType.Http.ToString ("g") , tandis que la valeur
apiType.Value.ToString ("g") ne sera jamais renvoyée.
V3022 L' expression 'automationJob! = Null && automationJob == null' est toujours fausse. NodeConfigurationDeployment.cs 199 (Automation)
public NodeConfigurationDeployment( ...., Management.Automation.Models.Job automationJob = null, ....) { .... if (automationJob != null && automationJob == null) return; .... }
Code contre-intuitif. Deux contrôles qui se contredisent. La deuxième vérification de
null contient probablement la mauvaise variable.
V3022 L' expression est toujours fausse. DataFactoryClient.Encrypt.cs 37 (DataFactory)
public virtual string OnPremisesEncryptString(....) { .... if ( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService && linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService && linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService && (value == null || value.Length == 0)) { throw new ArgumentNullException("value"); } .... }
Le chèque est inutile et l'exception ne sera jamais levée. La condition requiert l'égalité de la variable
LinkedServiceType simultanée à trois valeurs différentes. Les opérateurs && et || sont susceptibles d'être confus. Code fixe:
if (( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService || linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService || linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService) && (value == null || value.Length == 0)) ....
V3022 L' expression 'Ekus == null' est toujours fausse. PSKeyVaultCertificatePolicy.cs 129 (KeyVault)
internal CertificatePolicy ToCertificatePolicy() { .... if (Ekus != null) { x509CertificateProperties.Ekus = Ekus == null ? null : new List<string>(Ekus); } .... }
Contrôle redondant de la variable
Ekus pour
null . C'est probablement bien, mais le code n'a pas l'air sympa.
V3023 Envisagez d'inspecter cette expression. L'expression est excessive ou contient une erreur d'impression. PolicyRetentionObjects.cs 207 (RecoveryServices)
public virtual void Validate() { if (RetentionTimes == null || RetentionTimes.Count == 0 || RetentionTimes.Count != 1) { throw new ArgumentException( Resources.InvalidRetentionTimesInPolicyException); } }
Voici un contrôle excessif ou une condition excessive. La vérification
RetentionTimes.Count == 0 est inutile, car après cela, la vérification
RetentionTimes.Count! = 1 suit.
V3025 Format incorrect. Un nombre différent d'éléments de format est attendu lors de l'appel de la fonction 'Format'. Arguments non utilisés: this.ResourceGroupName. NewScheduledQueryRuleCommand.cs 117 (Moniteur)
protected override void ProcessRecordInternal() { .... if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {0}", this.Name, this.ResourceGroupName))) { .... } .... }
Une erreur dans la ligne de formatage. Le spécificateur
{0} est utilisé deux fois et la méthode
Format reçoit deux arguments. Voici la bonne version:
if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {1}", this.Name, this.ResourceGroupName))) ....
Une autre erreur similaire:
- V3025 Format incorrect. Un nombre différent d'éléments de format est attendu lors de l'appel de la fonction 'Format'. Arguments non utilisés: this.ResourceGroupName. RemoveScheduledQueryRuleCommand.cs 88 (Moniteur)
V3042 Exception
NullReferenceException possible. Le '?.' et '.' les opérateurs sont utilisés pour accéder aux membres de l'objet 'imageAndOsType' VirtualMachineScaleSetStrategy.cs 81 (Compute)
internal static ResourceConfig<VirtualMachineScaleSet> CreateVirtualMachineScaleSetConfig(...., ImageAndOsType imageAndOsType, ....) { .... VirtualMachineProfile = new VirtualMachineScaleSetVMProfile { OsProfile = new VirtualMachineScaleSetOSProfile { ...., WindowsConfiguration = imageAndOsType.CreateWindowsConfiguration(),
Lors de la création de l'objet
VirtualMachineScaleSetVMProfile , la variable
imageAndOsType est vérifiée pour
null sans aucune vérification préliminaire. Cependant, lors de la création de
VirtualMachineScaleSetStorageProfile , cette variable est déjà vérifiée à l'aide de l'opérateur d'accès conditionnel, même deux fois. Le code ne semble pas sûr.
V3042 Exception
NullReferenceException possible. Le '?.' et '.' les opérateurs sont utilisés pour accéder aux membres de l'objet 'existingContacts' RemoveAzureKeyVaultCertificateContact.cs 123 (KeyVault)
public override void ExecuteCmdlet() { .... List<PSKeyVaultCertificateContact> existingContacts; try { existingContacts = this.DataServiceClient. GetCertificateContacts(VaultName)?.ToList(); } catch (KeyVaultErrorException exception) { .... existingContacts = null; } foreach (var email in EmailAddress) { existingContacts.RemoveAll(....);
Dans l'exécution normale et suite à la gestion d'une exception, la variable
existingContacts peut obtenir la valeur
nulle , après quoi l'exécution se poursuivra. Plus loin dans le code, cette variable est utilisée sans raison particulière.
V3066 Ordre incorrect possible des arguments passés à la méthode 'PersistSyncServerRegistration': 'storageSyncServiceUid' et 'discoveryUri'. EcsManagementInteropClient.cs 364 (StorageSync)
public class EcsManagementInteropClient : IEcsManagement { .... public int PersistSyncServerRegistration(....) { return m_managementObject.PersistSyncServerRegistration( serviceUri, subscriptionId, storageSyncServiceName, resourceGroupName, clusterId, clusterName, storageSyncServiceUid,
L'analyseur soupçonne que l'ordre des arguments de la méthode
PersistSyncServerRegistration est confus. Déclaration de méthode:
public interface IEcsManagement : IDisposable { .... int PersistSyncServerRegistration( [In, MarshalAs(UnmanagedType.BStr)] string serviceUri, [In, MarshalAs(UnmanagedType.BStr)] string subscriptionId, [In, MarshalAs(UnmanagedType.BStr)] string storageSyncServiceName, [In, MarshalAs(UnmanagedType.BStr)] string resourceGroupName, [In, MarshalAs(UnmanagedType.BStr)] string clusterId, [In, MarshalAs(UnmanagedType.BStr)] string clusterName, [In, MarshalAs(UnmanagedType.BStr)] string discoveryUri,
En effet, quelque chose ne va pas ici avec les arguments numéro sept et huit. L'auteur doit vérifier le code.
V3077 Le setter de la propriété 'GetGuid' n'utilise pas son paramètre 'value'. RecoveryServicesBackupCmdletBase.cs 54 (RecoveryServices)
public abstract class RecoveryServicesBackupCmdletBase : AzureRMCmdlet { .... static string _guid; protected static string GetGuid { get { return _guid; } set { _guid = Guid.NewGuid().ToString(); } } .... }
Le setter n'utilise pas le paramètre passé. Au lieu de cela, il crée un nouveau GUID et l'affecte au champ
_guid . Je pense que la plupart des lecteurs conviendraient qu'un tel code semble au moins laid. Cette construction n'est pas très pratique à utiliser: lors de la (re) initialisation de la propriété
GetGuid , il faut lui assigner une fausse valeur, ce qui n'est pas très évident. Mais surtout, j'ai été amusé par la façon dont les auteurs ont utilisé ce modèle. Il n'y a qu'un seul endroit, où
GetGuid est géré. Découvrez-le:
public override void ExecuteCmdlet() { .... var itemResponse = ServiceClientAdapter.CreateOrUpdateProtectionIntent( GetGuid ?? Guid.NewGuid().ToString(), ....); .... }
Génial!
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 (Ressources)
public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id";
L'analyseur a signalé une erreur possible dans la chaîne affectée à la constante
GroupName . La conclusion est basée sur une analyse empirique d'autres affectations, en tenant compte des noms des variables. Je pense que dans ce cas, l'analyseur a raison, et la valeur des constantes
GroupName devrait être une sorte de "nom du groupe de gestion". L'erreur s'est probablement produite en raison du fait que la valeur de la constante
GroupId a été copiée, mais n'a pas été modifiée.
Une autre erreur similaire:
- V3091 Analyse empirique. Il est possible qu'une faute de frappe soit présente à l'intérieur du littéral de chaîne. Le mot «Nom» est suspect. ParamHelpMsgs.cs 153 (RecoveryServices)
V3093 Le '|' L'opérateur évalue les deux opérandes. Peut-être un court-circuit '||' l'opérateur doit être utilisé à la place. PSKeyVaultCertificatePolicy.cs 114 (KeyVault)
internal CertificatePolicy ToCertificatePolicy() { .... if (!string.IsNullOrWhiteSpace(SubjectName) || DnsNames != null || Ekus != null || KeyUsage != null |
Dans ce fragment, une erreur peut se produire et dans le bloc
if entre deux dernières conditions, le || peut avoir été utilisé. Mais comme cela arrive souvent, seul le développeur peut donner la bonne réponse.
V3095 L'objet 'certificate' a été utilisé avant d'être vérifié par rapport à null. Vérifiez les lignes: 41, 43. CertificateInfo.cs 41 (Automation)
public CertificateInfo( ...., Azure.Management.Automation.Models.Certificate certificate) { .... this.Name = certificate.Name; if (certificate == null) return; .... }
Classique. D'abord, l'objet est utilisé et ce n'est qu'après que la référence est vérifiée pour
null . Nous rencontrons
très souvent de telles erreurs. Prenons une autre erreur similaire.
V3095 L'objet 'clusterCred' a été utilisé avant d'être vérifié par rapport à null. Vérifiez les lignes: 115, 118. InvokeHiveCommand.cs 115 (HDInsight)
public override void ExecuteCmdlet() { .... _credential = new BasicAuthenticationCloudCredentials { Username = clusterCred.UserName, Password = clusterCred.Password.ConvertToString() }; if (clusterConnection == null || clusterCred == null) .... }
Voici quelques erreurs similaires:
- V3095 L'objet '_profile' a été utilisé avant d'être vérifié par rapport à null. Vérifiez les lignes: 47, 49. RMProfileClient.cs 47 (Comptes)
- V3095 L'objet 'this.LoadBalancer.BackendAddressPools' a été utilisé avant d'être vérifié par rapport à null. Vérifiez les lignes: 56, 63. AddAzureRmLoadBalancerBackendAddressPoolConfigCommand.cs 56 (CognitiveServices)
- De manière générale, j'ai vu de nombreuses erreurs V3095 dans le code Azure PowerShell. Mais tous sont assez similaires, je ne m'attarderai donc pas sur cette question.
V3125 L'objet 'startTime' a été utilisé après avoir été vérifié par rapport à null. Vérifiez les lignes: 1752, 1738. AutomationPSClientDSC.cs 1752 (Automation)
private string GetNodeReportListFilterString( ...., DateTimeOffset? startTime, ...., DateTimeOffset? lastModifiedTime) { .... if (startTime.HasValue) { odataFilter.Add("properties/startTime ge " + this.FormatDateTime(startTime.Value));
Il s'agit également d'un type d'erreurs assez répandu. La variable
startTime est vérifiée pour une présence de valeur lors de sa première utilisation. Mais cela ne se fait pas lors de l'utilisation ultérieure. Eh bien, la situation peut être encore pire. Regardez le deuxième bloc
if . Je pense que la variable
startTime ne doit pas du tout être ici. Tout d'abord, il n'y a pas de vérification de la présence d'une valeur avant son utilisation. Deuxièmement, la chaîne formée pour être passée à la méthode
Add confirme également ma suggestion. Une autre variable
(lastModifiedTime ) est mentionnée dans la première partie de cette chaîne.
V3125 L'objet 'firstPage' a été utilisé après avoir été vérifié par rapport à null. Vérifiez les lignes: 113, 108. IntegrationAccountAgreementOperations.cs 113 (LogicApp)
public IList<IntegrationAccountAgreement> ListIntegrationAccountAgreements(....) { var compositeList = new List<IntegrationAccountAgreement>(); var firstPage = this.LogicManagementClient. IntegrationAccountAgreements.List(....); if (firstPage != null) { compositeList.AddRange(firstPage); } if (!string.IsNullOrEmpty(firstPage.NextPageLink))
Une autre erreur évidente. La variable
firstPage n'est pas utilisée en toute sécurité malgré le fait que plus tôt dans le code, cette variable est déjà utilisée en étant préalablement vérifiée pour
null .
J'ai trouvé encore plus d'avertissements
V3125 dans le code Azure PowerShell que ceux
V3095 décrits ci-dessus. Tous sont également du même type. Je pense que deux d'entre eux que nous avons considérés suffisent.
V3137 La variable 'apiVersionSetId' est affectée mais n'est pas utilisée à la fin de la fonction. GetAzureApiManagementApiVersionSet.cs 69 (ApiManagement)
public String ApiVersionSetId { get; set; } .... public override void ExecuteApiManagementCmdlet() { .... string apiVersionSetId; if (ParameterSetName.Equals(ContextParameterSet)) { .... apiVersionSetId = ApiVersionSetId; } else { apiVersionSetId = ....; } if (string.IsNullOrEmpty(ApiVersionSetId))
L'analyseur signale que la variable locale
apiVersionSetId a été initialisée, mais n'a été utilisée en aucune façon. Ce motif indique souvent une erreur. Je pense que dans ce cas, il s'agit très probablement d'une erreur, en particulier compte tenu du fait que le nom de la variable locale
apiVersionSetId et le nom de la propriété
ApiVersionSetId ne diffèrent que par le cas de la première lettre. Jetez un œil au code. Après avoir initialisé la
propriété apiVersionSetId (d'une manière ou d'une autre), seule la propriété
ApiVersionSetId est utilisée plus loin dans le code. Cela semble extrêmement suspect.
V3137 La variable 'cacheId' est affectée mais n'est pas utilisée à la fin de la fonction. RemoveAzureApiManagementCache.cs 94 (ApiManagement)
public String CacheId { get; set; } .... public override void ExecuteApiManagementCmdlet() { .... string cacheId; if (....) { .... cacheId = InputObject.CacheId; } else if (....) { .... cacheId = cache.CacheId; } else { .... cacheId = CacheId; } var actionDescription = string.Format(...., CacheId);
C'est le cas qui est presque le même que celui décrit précédemment. La variable locale
cacheId n'est en aucun cas utilisée après l'initialisation. Au lieu de cela, une autre propriété avec un nom très similaire
CacheId est utilisée. Je ne sais pas avec certitude, c'est peut-être juste un modèle de programmation des développeurs Azure PowerShell. Quoi qu'il en soit, cela ressemble à une erreur.
V3143 Le paramètre 'value' est réécrit dans un
configurateur de propriétés et n'est plus utilisé par la suite. NewAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
[Parameter(Mandatory = false, HelpMessage = "The integration account partner type.", ValueFromPipelineByPropertyName = false)] [ValidateSet("B2B", IgnoreCase = false)] [ValidateNotNullOrEmpty] public string PartnerType { get { return this.partnerType; } set { value = this.partnerType; }
Le champ
partnerType est déclaré de la manière suivante:
Malgré le nom de la solution (LogicApp) où une erreur a été détectée, je n'y trouve pas de logique. La modification de la
valeur dans le setter n'est pas rare, mais dans ce cas, il s'agit d'une perte de la valeur d'origine. Ça a l'air bizarre. Dans le code, la propriété n'est lue qu'une seule fois. Peut-être devons-nous demander à nouveau l'avis d'experts. Peut-être que je ne comprends tout simplement pas. Le fait est que je suis tombé sur plusieurs mêmes schémas:
- V3143 Le paramètre 'value' est réécrit dans un configurateur de propriétés et n'est plus utilisé par la suite. NewAzureIntegrationAccountSchemaCommand.cs 79 (LogicApp)
- V3143 Le paramètre 'value' est réécrit dans un configurateur de propriétés et n'est plus utilisé par la suite. NewAzureIntegrationAccountSchemaCommand.cs 87 (LogicApp)
- V3143 Le paramètre 'value' est réécrit dans un configurateur de propriétés et n'est plus utilisé par la suite. UpdateAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
- V3143 Le paramètre 'value' est réécrit dans un configurateur de propriétés et n'est plus utilisé par la suite. UpdateAzureIntegrationAccountSchemaCommand.cs 80 (LogicApp)
- V3143 Le paramètre 'value' est réécrit dans un configurateur de propriétés et n'est plus utilisé par la suite. UpdateAzureIntegrationAccountSchemaCommand.cs 88 (LogicApp)
Conclusion
Ce sont tous des bogues intéressants qui ont été trouvés dans le code Azure PowerShell. Les amateurs et ceux qui sont intéressés sont invités à examiner eux-mêmes les erreurs dans ce projet (ou tout autre). Je pourrais probablement manquer quelque chose de décalé. Pour effectuer la révision, il vous suffit de télécharger et d'installer
PVS-Studio .
Merci d'avoir lu jusqu'à la fin. Et, bien sûr, du code sans code pour tout le monde!