Hallo an alle. Heute haben wir ein weiteres Microsoft-Projekt auf dem Prüfstand. Anhand des Titels dieses Artikels können Sie sich vorstellen, dass die Entwickler uns diesmal nicht mit einer großen Anzahl von Fehlern "gefallen" haben. Wir hoffen, dass die Autoren des Projekts vom Titel nicht beleidigt werden. Immerhin ist eine kleine Anzahl von Fehlern großartig, nicht wahr? Es ist uns jedoch immer noch gelungen, im Azure PowerShell-Code etwas Interessantes zu finden. Wir empfehlen, die Funktionen dieses Projekts kennenzulernen und Fehler zu überprüfen, die mit dem PVS-Studio C # -Analysator festgestellt wurden.
Über das Projekt
Azure PowerShell ist eine Reihe von Commandlets (
Cmdlet ), mit denen Sie
Azure- Ressourcen direkt über die
PowerShell- Befehlszeile verwalten können. Der Hauptzweck dieses Sets besteht darin, den Lernprozess zu vereinfachen und die Entwicklung für Azure schnell zu starten. Azure PowerShell bietet Administratoren und Entwicklern überzeugende Funktionen zum Erstellen, Bereitstellen und Verwalten von Microsoft Azure-Anwendungen.
Azure PowerShell wurde in der .NET Standard-Umgebung entwickelt und wird von PowerShell 5.1 für Windows und PowerShell 6.x und höher für alle Plattformen unterstützt. Der Azure PowerShell-
Quellcode ist auf GitHub verfügbar.
In letzter Zeit habe ich oft Microsoft-Projekte zur Überprüfung erhalten. Meiner Meinung nach ist die Qualität dieser Projekte in der Regel erstklassig. Obwohl natürlich nicht ohne Ausnahmen, wie im Artikel "
WinForms: Errors, Holmes " beschrieben. Aber diesmal ist alles in Ordnung. Das Projekt ist groß: 6845 .cs-Quellcodedateien enthalten ungefähr 700.000 Zeilen, ausgenommen leere (ich habe Tests und Warnungen der dritten Sicherheitsstufe nicht berücksichtigt). Für diese Codemenge wurden nur sehr wenige Fehler gefunden: nicht mehr als hundert. Es gab ziemlich viele ähnliche Fälle, deshalb habe ich die interessantesten für den Artikel ausgewählt. Wie üblich habe ich Fehler nach den Nummern der PVS-Studio-Warnungen sortiert.
Außerdem bin ich auf einige Codefragmente gestoßen, die wie Fehler aussahen, aber nicht als definitiv fehlerhaft erkannt werden konnten, da ich mit den Besonderheiten der PowerShell-Entwicklung nicht vertraut genug bin. Ich hoffe, dass es unter den Lesern Spezialisten in dieser Ausgabe gibt, die mir helfen werden. Ich werde es unten im Detail beschreiben.
Vor dem Feedback-Teil möchte ich die spezifische Struktur des Projekts erwähnen. Der Azure PowerShell-Quellcode besteht aus mehr als siebzig Visual Studio-Lösungen. Einige Lösungen umfassen Projekte von anderen. Diese Struktur verlangsamte die Analyse ein wenig (nicht viel). Trotzdem verursachte der Scheck keine weiteren Schwierigkeiten. Der Einfachheit halber werde ich in der Fehlermeldung (in Klammern) den Namen der Lösung angeben, bei der der Fehler gefunden wurde.
Analyseergebnisse
V3001 Links und rechts vom '||' befinden sich identische Unterausdrücke 'strTimespan.Contains ("M")'. Betreiber. 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")) .... }
Ein Beispiel für einen ziemlich offensichtlichen Fehler, den nur ein Entwickler beheben kann. In diesem Fall ist es absolut unklar, ob es sich bei einer von zwei letzten Prüfungen um Codeduplizierungen handelt, die nichts betreffen oder etwas anderes anstelle von
"M" stattfinden müssen .
V3001 Links und rechts vom Operator '&&' befinden sich identische Unterausdrücke 'this.AggregationType! = Null'. GetAzureRmMetricCommand.cs 156 (Monitor)
public AggregationType? AggregationType { get; set; } .... protected override void ProcessRecordInternal() { .... string aggregation = (this.AggregationType != null && this.AggregationType.HasValue) ? this.AggregationType.Value.ToString() : null; .... }
Hier liegt wahrscheinlich kein Fehler vor. Dies ist ein Beispiel für redundanten Code. Manchmal weist ein solcher Code auf mangelndes Wissen des Entwicklers hin. Der Punkt ist, dass die Prüfungen
this.AggregationType! = Null und
this.AggregationType.HasValue identisch sind. Es reicht aus, nur einen von ihnen (einen) zu verwenden. Persönlich bevorzuge ich die Option mit
HasValue: string aggregation = this.AggregationType.HasValue ? this.AggregationType.Value.ToString() : null;
V3003 Die Verwendung des
Musters 'if (A) {...} else if (A) {...}' wurde erkannt. Es besteht die Wahrscheinlichkeit eines logischen Fehlers. Überprüfen Sie die Zeilen: 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 ); } .... }
Zwei
weitere, wenn Blöcke absolut identisch sind, einschließlich des Zustands und des Körpers des Blocks. Solche Fehler treten normalerweise bei Verwendung der Copy-Paste-Methode auf. Das Problem hier ist wieder die Kritikalität des Fehlers. Wenn es sich nicht um eine einfache Codeduplizierung handelt, kann es sich um die fehlende erforderliche Überprüfung und die entsprechenden Maßnahmen handeln. Der Autor muss den Code definitiv bearbeiten.
V3005 Die Variable 'this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent' wird sich selbst zugewiesen. SetAzureVMOperatingSystemCommand.cs 298 (Compute)
public override void ExecuteCmdlet() { ....
Der Wert der Eigenschaft wird selbst zugewiesen. Schauen Sie sich die Erklärung an:
[JsonProperty(PropertyName = "provisionVMAgent")] public bool? ProvisionVMAgent { get; set; }
In der
JsonProperty- Beschreibung heißt es: "Weist den Newtonsoft.Json.JsonSerializer an, das Mitglied immer mit dem angegebenen Namen zu serialisieren." Es scheint, dass alles schuldlos ist und der offensichtliche Fehler gemacht wurde. Die explizite Verwendung
dieser Option für den Zugriff auf die Immobilie ist ebenfalls ziemlich verwirrend. Vielleicht wurde stattdessen nicht fälschlicherweise eine andere Variable angegeben
. Aber lassen Sie uns nicht zu Schlussfolgerungen springen. Tatsache ist, dass ich auf eine Menge solcher Aufgaben gestoßen bin (eine Eigenschaft ist selbst zugewiesen). Hier ist ein Beispiel für eine Zuweisung, die einem Fehler sehr ähnlich ist:
V3005 Die Variable 'this.LastHeartbeat' wird sich selbst zugewiesen. PSFabricDetails.cs 804 (RecoveryServices)
public ASRInMageAzureV2SpecificRPIDetails( InMageAzureV2ReplicationDetails details) { this.LastHeartbeat = this.LastHeartbeat;
Schauen wir uns die zweite und die nachfolgenden Aufgaben genauer an. Im rechten Teil des Ausdrucks finden stattdessen
Details statt
. Schauen Sie sich nun die Deklaration der Eigenschaft
this.LastHeartbeat an :
public DateTime? LastHeartbeat { get; set; }
Zuletzt suchen wir die gleichnamige Eigenschaft in der
InMageAzureV2ReplicationDetails- Klasse. Ein solches Eigentum wird dort deklariert:
public class InMageAzureV2ReplicationDetails : ReplicationProviderSpecificSettings { .... [JsonProperty(PropertyName = "lastHeartbeat")] public DateTime? LastHeartbeat { get; set; } .... }
Nun, in diesem Fall bin ich bereit zuzugeben, dass es ein echter Fehler ist. Aber was sollen wir mit den nächsten Warnungen tun? Im Gegensatz zu zwei vorherigen Codefragmenten gibt es mehrere selbst zugewiesene Eigenschaften. Nun, das sieht weniger nach einem Fehler aus:
- V3005 Die Variable 'this.ResourceGroupName' wird sich selbst zugewiesen. RemoveAzureRmExpressRouteConnectionCommand.cs 84 (CognitiveServices)
- V3005 Die Variable 'this.ExpressRouteGatewayName' wird sich selbst zugewiesen. RemoveAzureRmExpressRouteConnectionCommand.cs 85 (CognitiveServices)
- V3005 Die Variable 'this.Name' wird sich selbst zugewiesen. 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; } .... } .... }
Die
Execute- Methode enthält die Selbstzuweisungen von drei Eigenschaften in einer Reihe.
Für alle Fälle habe ich die vollständige Deklaration der Klasse
RemoveExpressRouteConnectionCommand und aller ihrer Attribute sowie die
ResourceGroupName- Eigenschaftsdeklaration zitiert (die beiden anderen Eigenschaften werden auf ähnliche Weise deklariert). Es waren diese Warnungen, die mich über die Frage nachdenken ließen: "Ist es ein Fehler?" Ich vermute, dass hier eine interne Magie der PowerShell-Entwicklung stattfindet. Ich hoffe, dass es unter den Lesern Experten gibt, die über dieses Thema informiert sind. Ich bin nicht bereit, in diesem Fall irgendwelche Schlussfolgerungen zu ziehen.
V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 259 (RecoveryServices)
private void StartRPITestFailover() { .... if (....) { .... } else { new ArgumentException( Resources .UnsupportedDirectionForTFO);
Das Schlüsselwort
throw wird weggelassen. Und der Kommentar besagt, dass die Ausnahme nur ausgelöst werden muss. In der
RecoveryServices- Lösung sind mehrere ähnliche Fehler aufgetreten:
- V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 305 (RecoveryServices)
- V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 278 (RecoveryServices)
- V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 322 (RecoveryServices)
- V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 421 (RecoveryServices)
- V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 452 (RecoveryServices)
V3022 Der Ausdruck 'apiType.HasValue' ist immer falsch. 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 ?
Die Logik der Arbeit wurde gebrochen. Wenn
apiType einen Wert enthält, erreicht das Steuerelement den
Rückgabeausdruck am Ende der Methode nicht (alle
Switch- Zweige enthalten
return ). Andernfalls gibt die Methode immer
PsApiManagementApiType.Http.ToString ("g") zurück , während der Wert
apiType.Value.ToString ("g") niemals zurückgegeben wird.
V3022 Der Ausdruck 'automationJob! = Null && automationJob == null' ist immer falsch. NodeConfigurationDeployment.cs 199 (Automatisierung)
public NodeConfigurationDeployment( ...., Management.Automation.Models.Job automationJob = null, ....) { .... if (automationJob != null && automationJob == null) return; .... }
Kontraintuitiver Code. Zwei Schecks, die sich widersprechen. Wahrscheinlich enthält die zweite Prüfung auf
null die falsche Variable.
V3022 Ausdruck ist immer falsch. 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"); } .... }
Die Prüfung ist sinnlos und die Ausnahme wird niemals ausgelöst. Die Bedingung erfordert die gleichzeitige
Gleichheit der Variablen
linkedServiceType mit drei verschiedenen Werten. Die Operatoren && und || sind wahrscheinlich verwirrt. Fester Code:
if (( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService || linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService || linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService) && (value == null || value.Length == 0)) ....
V3022 Der Ausdruck 'Ekus == null' ist immer falsch. PSKeyVaultCertificatePolicy.cs 129 (KeyVault)
internal CertificatePolicy ToCertificatePolicy() { .... if (Ekus != null) { x509CertificateProperties.Ekus = Ekus == null ? null : new List<string>(Ekus); } .... }
Redundante Überprüfung der
Ekus- Variablen auf
Null . Es ist wahrscheinlich in Ordnung, aber der Code sieht nicht gut aus.
V3023 Überprüfen Sie diesen Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. PolicyRetentionObjects.cs 207 (RecoveryServices)
public virtual void Validate() { if (RetentionTimes == null || RetentionTimes.Count == 0 || RetentionTimes.Count != 1) { throw new ArgumentException( Resources.InvalidRetentionTimesInPolicyException); } }
Hier ist eine übermäßige Überprüfung oder ein übermäßiger Zustand. Die Prüfung
RetentionTimes.Count == 0 ist sinnlos, da danach die Prüfung
RetentionTimes.Count! = 1 folgt.
V3025 Falsches Format. Beim Aufrufen der Funktion 'Format' wird eine andere Anzahl von Formatelementen erwartet. Nicht verwendete Argumente: this.ResourceGroupName. NewScheduledQueryRuleCommand.cs 117 (Monitor)
protected override void ProcessRecordInternal() { .... if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {0}", this.Name, this.ResourceGroupName))) { .... } .... }
Ein Fehler in der Formatierungszeile. Der Bezeichner
{0} wird zweimal verwendet, und der
Format- Methode werden zwei Argumente übergeben. Hier ist die richtige Version:
if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {1}", this.Name, this.ResourceGroupName))) ....
Ein weiterer ähnlicher Fehler:
- V3025 Falsches Format. Beim Aufrufen der Funktion 'Format' wird eine andere Anzahl von Formatelementen erwartet. Nicht verwendete Argumente: this.ResourceGroupName. RemoveScheduledQueryRuleCommand.cs 88 (Monitor)
V3042 Mögliche NullReferenceException. Das '?.' und '.' Operatoren werden für den Zugriff auf Mitglieder des Objekts 'imageAndOsType' VirtualMachineScaleSetStrategy.cs 81 (Compute) verwendet.
internal static ResourceConfig<VirtualMachineScaleSet> CreateVirtualMachineScaleSetConfig(...., ImageAndOsType imageAndOsType, ....) { .... VirtualMachineProfile = new VirtualMachineScaleSetVMProfile { OsProfile = new VirtualMachineScaleSetOSProfile { ...., WindowsConfiguration = imageAndOsType.CreateWindowsConfiguration(),
Beim Erstellen des
VirtualMachineScaleSetVMProfile- Objekts wird die Variable
imageAndOsType ohne vorherige Überprüfung auf
null überprüft. Beim Erstellen von
VirtualMachineScaleSetStorageProfile wird diese Variable jedoch bereits zweimal mit dem Operator für bedingten Zugriff überprüft. Der Code sieht nicht sicher aus.
V3042 Mögliche NullReferenceException. Das '?.' und '.' Operatoren werden für den Zugriff auf Mitglieder des Objekts 'availableContacts' verwendet. 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(....);
Sowohl bei der normalen Ausführung als auch als Ergebnis der Behandlung einer Ausnahme kann die Variable
existierende Kontakte den
Nullwert erhalten , wonach die Ausführung fortgesetzt wird. Weiter im Code wird diese Variable ohne besonderen Grund verwendet.
V3066 Möglicherweise falsche Reihenfolge der an die Methode 'PersistSyncServerRegistration' übergebenen Argumente: 'storageSyncServiceUid' und 'DiscoveryUri'. EcsManagementInteropClient.cs 364 (StorageSync)
public class EcsManagementInteropClient : IEcsManagement { .... public int PersistSyncServerRegistration(....) { return m_managementObject.PersistSyncServerRegistration( serviceUri, subscriptionId, storageSyncServiceName, resourceGroupName, clusterId, clusterName, storageSyncServiceUid,
Der Analysator vermutete, dass die Reihenfolge der Argumente der
PersistSyncServerRegistration- Methode verwirrt ist. Erklärung der Methode:
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,
In der Tat stimmt hier etwas mit den Argumenten Nummer sieben und acht nicht. Der Autor muss den Code überprüfen.
V3077 Der Setter der Eigenschaft 'GetGuid' verwendet seinen Parameter 'value' nicht. RecoveryServicesBackupCmdletBase.cs 54 (RecoveryServices)
public abstract class RecoveryServicesBackupCmdletBase : AzureRMCmdlet { .... static string _guid; protected static string GetGuid { get { return _guid; } set { _guid = Guid.NewGuid().ToString(); } } .... }
Der Setter verwendet den übergebenen Parameter nicht. Stattdessen wird eine neue GUID erstellt und dem Feld
_guid zugewiesen . Ich denke, die meisten Leser würden zustimmen, dass ein solcher Code zumindest hässlich aussieht. Diese Konstruktion ist nicht sehr bequem zu verwenden: Wenn die
GetGuid- Eigenschaft (neu) initialisiert wird, muss ihr ein gefälschter Wert zugewiesen werden, was nicht sehr offensichtlich ist. Vor allem aber hat mich die Art und Weise, wie Autoren dieses Muster verwendeten, amüsiert. Es gibt nur einen Ort, an dem
GetGuid verwaltet wird. Probieren Sie es aus:
public override void ExecuteCmdlet() { .... var itemResponse = ServiceClientAdapter.CreateOrUpdateProtectionIntent( GetGuid ?? Guid.NewGuid().ToString(), ....); .... }
Genial!
V3091 Empirische Analyse. Möglicherweise ist im Zeichenfolgenliteral ein Tippfehler vorhanden: "Verwaltungsgruppen-ID". Das 'Id'-Wort ist verdächtig. Constants.cs 36 (Ressourcen)
public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id";
Der Analysator hat auf einen möglichen Fehler in der zugewiesenen Zeichenfolge für die
GroupName- Konstante
hingewiesen . Die Schlussfolgerung basiert auf einer empirischen Analyse anderer Zuordnungen unter Berücksichtigung der Namen von Variablen. Ich denke, dass in diesem Fall der Analysator richtig ist und der Wert der
GroupName- Konstanten eine Art "Management Group Name" sein sollte. Wahrscheinlich ist der Fehler darauf zurückzuführen, dass der Wert für die
GroupId- Konstante kopiert, aber nicht geändert wurde.
Ein weiterer ähnlicher Fehler:
- V3091 Empirische Analyse. Möglicherweise ist im Zeichenfolgenliteral ein Tippfehler vorhanden. Das Wort 'Name' ist verdächtig. ParamHelpMsgs.cs 153 (RecoveryServices)
V3093 Das '|' Der Operator wertet beide Operanden aus. Vielleicht ein Kurzschluss '||' Stattdessen sollte der Operator verwendet werden. PSKeyVaultCertificatePolicy.cs 114 (KeyVault)
internal CertificatePolicy ToCertificatePolicy() { .... if (!string.IsNullOrWhiteSpace(SubjectName) || DnsNames != null || Ekus != null || KeyUsage != null |
In diesem Fragment kann ein Fehler auftreten und im
if- Block zwischen zwei letzten Bedingungen das || Möglicherweise wurde der Operator verwendet. Aber wie so oft kann nur der Entwickler die richtige Antwort geben.
V3095 Das 'Zertifikat'-Objekt wurde verwendet, bevor es gegen Null verifiziert wurde. Überprüfen Sie die Zeilen: 41, 43. CertificateInfo.cs 41 (Automatisierung)
public CertificateInfo( ...., Azure.Management.Automation.Models.Certificate certificate) { .... this.Name = certificate.Name; if (certificate == null) return; .... }
Klassisch. Zuerst wird das Objekt verwendet und erst danach wird die Referenz auf
Null geprüft. Wir stoßen
sehr oft auf solche Fehler. Betrachten wir einen weiteren ähnlichen Fehler.
V3095 Das Objekt 'clusterCred' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 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) .... }
Hier sind einige ähnliche Fehler:
- V3095 Das Objekt '_profile' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 47, 49. RMProfileClient.cs 47 (Konten)
- V3095 Das Objekt 'this.LoadBalancer.BackendAddressPools' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 56, 63. AddAzureRmLoadBalancerBackendAddressPoolConfigCommand.cs 56 (CognitiveServices)
- Im Allgemeinen wurden im Azure PowerShell-Code viele V3095- Fehler angezeigt . Aber alle sind sich ziemlich ähnlich, deshalb werde ich mich nicht mit diesem Thema befassen.
V3125 Das 'startTime'-Objekt wurde verwendet, nachdem es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 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));
Es ist auch eine ziemlich weit verbreitete Art von Fehlern. Die Variable
startTime wird bei der ersten Verwendung auf das Vorhandensein eines Werts überprüft. Dies erfolgt jedoch nicht in der nachfolgenden Verwendung. Nun, die Situation kann noch schlimmer sein. Schauen Sie sich den zweiten
if- Block an. Ich denke, die Variable
startTime darf überhaupt nicht hier sein. Erstens gibt es keine Überprüfung auf das Vorhandensein eines Werts vor seiner Verwendung. Zweitens bestätigt die Zeichenfolge, die gebildet wird, um an die
Add- Methode übergeben zu werden, meinen Vorschlag. Eine weitere Variable
(lastModifiedTime ) wird im ersten Teil dieser Zeichenfolge erwähnt.
V3125 Das 'firstPage'-Objekt wurde verwendet, nachdem es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 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))
Ein weiterer offensichtlicher Fehler. Die Variable
firstPage wird unsicher verwendet, obwohl diese Variable bereits früher im Code verwendet wurde und vorläufig auf
null überprüft wurde.
Ich
habe im Azure PowerShell-Code noch mehr
V3125- Warnungen gefunden als
die oben beschriebenen
V3095- Warnungen. Alle von ihnen sind auch vom gleichen Typ. Ich denke, zwei davon, die wir in Betracht gezogen haben, sind genug.
V3137 Die Variable 'apiVersionSetId' wird zugewiesen, aber am Ende der Funktion nicht verwendet. 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))
Der Analysator meldet, dass die lokale Variable
apiVersionSetId initialisiert, aber in keiner Weise verwendet wurde. Oft weist dieses Muster auf einen Fehler hin. Ich denke, in diesem Fall handelt es sich höchstwahrscheinlich um einen Fehler, insbesondere unter Berücksichtigung der Tatsache, dass sich der Name der lokalen Variablen
apiVersionSetId und der Name der Eigenschaft
ApiVersionSetId nur durch den Fall des ersten Buchstabens unterscheiden. Schauen Sie sich den Code an. Nach der Initialisierung der
apiVersionSetId-Eigenschaft (auf die eine oder andere Weise) wird im Code nur die
ApiVersionSetId- Eigenschaft weiter verwendet. Es sieht sehr verdächtig aus.
V3137 Die Variable 'cacheId' wird zugewiesen, aber am Ende der Funktion nicht verwendet. 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);
Dies ist der Fall, der fast der gleiche ist wie der zuvor beschriebene. Die lokale Variable
cacheId wird nach der Initialisierung in keiner Weise verwendet. Stattdessen wird eine andere Eigenschaft mit einem sehr ähnlichen Namen
CacheId verwendet. Ich weiß es nicht genau. Vielleicht ist das nur ein Programmiermuster von Azure PowerShell-Entwicklern. Wie auch immer, es sieht nach einem Fehler aus.
V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. 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; }
Das Feld
partnerType wird folgendermaßen deklariert:
Trotz des Namens der Lösung (LogicApp), bei der ein Fehler festgestellt wurde, finde ich keine Logik darin. Das Ändern des
Werts im Setter ist nicht selten, aber in diesem Fall handelt es sich um einen Verlust des ursprünglichen Werts. Es sieht komisch aus. In der Code-Eigenschaft wird nur einmal gelesen. Vielleicht müssen wir noch einmal um Rat fragen. Vielleicht verstehe ich es einfach nicht. Der Punkt ist, dass ich auf mehrere gleiche Muster gestoßen bin:
- V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. NewAzureIntegrationAccountSchemaCommand.cs 79 (LogicApp)
- V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. NewAzureIntegrationAccountSchemaCommand.cs 87 (LogicApp)
- V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. UpdateAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
- V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. UpdateAzureIntegrationAccountSchemaCommand.cs 80 (LogicApp)
- V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. UpdateAzureIntegrationAccountSchemaCommand.cs 88 (LogicApp)
Fazit
Dies sind alles interessante Fehler, die im Azure PowerShell-Code gefunden wurden. Enthusiasten und Interessierte können Fehler in diesem (oder einem anderen) Projekt gerne selbst überprüfen. Ich könnte wahrscheinlich etwas Ungewöhnliches verpassen. Um die Überprüfung durchzuführen, müssen Sie nur
PVS-Studio herunterladen und installieren.
Vielen Dank für das Lesen bis zum Ende. Und natürlich fehlerfreien Code für alle!