Azure PowerShell: "kebanyakan tidak berbahaya"

Gambar 6

Halo semuanya. Hari ini kami memiliki proyek Microsoft lain yang diuji. Dengan judul artikel, Anda dapat menebak bahwa kali ini para pengembang tidak dapat menyenangkan kami dengan sejumlah besar kesalahan. Kami berharap bahwa penulis proyek tidak akan tersinggung dengan namanya. Bagaimanapun, sejumlah kecil kesalahan sangat bagus, bukan? Namun, sesuatu yang menarik ditemukan dalam kode Azure PowerShell. Kami sarankan agar Anda membiasakan diri dengan fitur-fitur proyek ini dan melihat kesalahan yang ditemukan pada PV # C-analyzer PVS-Studio.

Tentang proyek


Azure PowerShell adalah cmdlet yang memungkinkan Anda untuk mengelola sumber daya Azure langsung dari baris perintah PowerShell . Tujuan utama set ini adalah untuk menyederhanakan pembelajaran dan mulai cepat pengembangan untuk Azure. Azure PowerShell memberi para administrator dan pengembang fitur-fitur canggih untuk membuat, menyebarkan, dan mengelola aplikasi Microsoft Azure.

Azure PowerShell dikembangkan di lingkungan .NET Standard dan didukung oleh PowerShell 5.1 untuk Windows dan PowerShell 6.x dan lebih tinggi untuk semua platform. Kode sumber Azure PowerShell tersedia di GitHub.

Baru-baru ini, proyek Microsoft sering menarik perhatian saya. Menurut pendapat saya, kualitas proyek-proyek ini biasanya yang terbaik. Meskipun, tentu saja, bukan tanpa pengecualian, seperti artikel " WinForms: errors, Holmes ". Namun, kali ini semuanya normal. Proyek ini besar: 6845 file .cs kode sumber berisi sekitar 700 ribu baris, tidak termasuk kosong (tes, serta peringatan tingkat ketiga keandalan, saya tidak memperhitungkan). Ada sangat sedikit kesalahan untuk volume kode seperti itu: tidak lebih dari seratus. Ada cukup banyak situasi dengan jenis yang sama, jadi untuk artikel yang saya pilih positif yang paling menarik. Kesalahan, seperti yang biasa saya lakukan, diurutkan berdasarkan nomor diagnostik PVS-Studio.

Saya juga menemukan fragmen kode yang terlihat seperti kesalahan, tetapi saya tidak bisa membuat kesimpulan yang jelas tentang keberadaan masalah nyata, karena saya tidak cukup akrab dengan fitur desain untuk PowerShell. Saya berharap di antara pembaca akan ada ahli dalam masalah ini dan akan membantu saya. Tentang itu di bawah ini.

Sebelum dimulainya "pembekalan," saya perhatikan fitur proyek dalam hal strukturnya. Kode sumber Azure PowerShell terdiri dari lebih dari tujuh puluh solusi Visual Studio. Beberapa solusi termasuk proyek dari solusi lain. Struktur seperti itu memperlambat analisis sedikit (tidak banyak). Sisa verifikasi tidak menimbulkan kesulitan. Untuk kenyamanan, di baris pesan kesalahan (dalam tanda kurung) saya akan menunjukkan nama solusi di mana kesalahan ini terdeteksi.

Hasil Validasi


V3001 Ada sub-ekspresi identik 'strTimespan.Berisi ("M")' di sebelah kiri dan di sebelah kanan dari '||' operator. 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")) .... } 

Contoh kesalahan yang cukup jelas, yang hanya dapat diperbaiki oleh pengembang. Dalam hal ini, sama sekali tidak dapat dipahami apakah kita berurusan dengan duplikasi kode yang tidak mempengaruhi apa pun, atau bukannya "M" sesuatu yang lain harus muncul dalam salah satu dari dua pemeriksaan terakhir.

V3001 Ada sub-ekspresi identik 'this.AggregationType! = Null' di kiri dan di kanan operator '&&'. 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; .... } 

Mungkin tidak ada kesalahan di sini. Ini adalah contoh kode redundan. Terkadang kode seperti itu mengindikasikan tingkat pengetahuan pengembang yang tidak memadai. Faktanya adalah bahwa this.AggregationType! = Null dan this.AggregationType.HasValue cek identik. Cukup menggunakan salah satunya (apa saja). Secara pribadi, saya lebih suka opsi HasValue :

 string aggregation = this.AggregationType.HasValue ? this.AggregationType.Value.ToString() : null; 

V3003 Penggunaan pola 'jika (A) {...} else jika (A) {...}' terdeteksi. Ada kemungkinan kehadiran kesalahan logis. Periksa baris: 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 ); } .... } 

Dua lainnya jika balok benar-benar identik, termasuk kondisi dan tubuh balok. Kesalahan seperti itu biasanya dibuat ketika menggunakan metode salin-tempel dalam pekerjaan. Pertanyaannya lagi adalah kekritisan kesalahan ini. Jika ini bukan duplikasi kode yang sederhana, maka kita dapat berbicara tentang kurangnya verifikasi yang diperlukan dan serangkaian tindakan yang sesuai. Penulis perlu mengedit kode.

V3005 Variabel 'this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent' ditugaskan untuk dirinya sendiri. SetAzureVMOperatingSystemCommand.cs 298 (Hitung)

 public override void ExecuteCmdlet() { .... // OS Profile this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent = this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent; .... } 

Nilai properti ditugaskan untuk dirinya sendiri. Lihatlah iklannya:

 [JsonProperty(PropertyName = "provisionVMAgent")] public bool? ProvisionVMAgent { get; set; } 

Deskripsi JsonProperty mengatakan "Menginstruksikan Newtonsoft.Json.JsonSerializer untuk selalu membuat serial anggota dengan nama yang ditentukan". Tampaknya semuanya sederhana dan ada kesalahan yang jelas. Juga membingungkan adalah penggunaan eksplisit ini untuk mengakses properti. Mungkin, secara tidak sengaja, beberapa variabel lain tidak ditentukan selain ini . Tapi untuk saat ini, kami tidak akan menarik kesimpulan. Faktanya adalah bahwa dalam kode Azure PowerShell saya bertemu cukup banyak penugasan seperti itu (properti ditugaskan untuk dirinya sendiri). Berikut adalah contoh tugas yang sangat mirip dengan kesalahan:

V3005 Variabel 'this.LastHeartbeat' ditugaskan untuk dirinya sendiri. PSFabricDetails.cs 804 (RecoveryServices)

 public ASRInMageAzureV2SpecificRPIDetails( InMageAzureV2ReplicationDetails details) { this.LastHeartbeat = this.LastHeartbeat; // <= this.RecoveryAvailabilitySetId = details.RecoveryAvailabilitySetId; this.AgentVersion = details.AgentVersion; this.DiscoveryType = details.DiscoveryType; .... } 

Perhatikan tugas kedua dan selanjutnya. Di sisi kanan ekspresi, bukan ini yang muncul sama sekali, tetapi detail . Lihatlah deklarasi properti ini. Properti LastHeartbeat :

 public DateTime? LastHeartbeat { get; set; } 

Terakhir, cari properti dengan nama yang sama di kelas InMageAzureV2ReplicationDetails . Properti seperti itu dinyatakan di sana:

 public class InMageAzureV2ReplicationDetails : ReplicationProviderSpecificSettings { .... [JsonProperty(PropertyName = "lastHeartbeat")] public DateTime? LastHeartbeat { get; set; } .... } 

Nah, dalam hal ini, saya siap mengakui pemicuan ini adalah kesalahan nyata. Tapi apa yang harus dilakukan dengan pemicu berikut? Di dalamnya, tidak seperti dua fragmen kode sebelumnya, ada beberapa penugasan properti untuk diri mereka sendiri. Ini sudah kurang seperti kesalahan:

  • V3005 Variabel 'this.ResourceGroupName' ditugaskan untuk dirinya sendiri. RemoveAzureRmExpressRouteConnectionCommand.cs 84 (CognitiveServices)
  • V3005 Variabel 'this.ExpressRouteGatewayName' ditugaskan untuk dirinya sendiri. RemoveAzureRmExpressRouteConnectionCommand.cs 85 (CognitiveServices)
  • V3005 Variabel 'this.Name' ditugaskan untuk dirinya sendiri. 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; } .... } .... } 

Metode Execute berisi tiga penetapan properti secara berurutan. Untuk berjaga-jaga, saya memberikan deklarasi lengkap dari kelas RemoveExpressRouteConnectionCommand dengan semua atributnya, serta deklarasi properti ResourceGroupName (dua properti lainnya dideklarasikan dengan cara yang sama). Memicu yang membuat saya berpikir tentang pertanyaan: "Apakah ini kesalahan?" Saya menduga bahwa beberapa jenis sihir internal pengembangan PowerShell dapat terjadi di sini. Saya berharap di antara pembaca ada ahli yang memiliki pengetahuan dalam hal ini. Saya belum siap untuk membuat kesimpulan dalam kasus ini.

V3006 Objek telah dibuat tetapi tidak sedang digunakan. Kata kunci 'lempar' bisa hilang: lempar ArgumentException baru (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 259 (RecoveryServices)

 private void StartRPITestFailover() { .... if (....) { .... } else { new ArgumentException( Resources .UnsupportedDirectionForTFO); // Throw Unsupported Direction // Exception } .... } 

Melewati kata kunci lemparan . Terlebih lagi, komentar tersebut mengatakan bahwa pengecualian hanya boleh dibuang. Dalam solusi RecoveryServices , saya menemukan beberapa kesalahan serupa:

  • V3006 Objek telah dibuat tetapi tidak sedang digunakan. Kata kunci 'lempar' bisa hilang: lempar ArgumentException baru (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 305 (RecoveryServices)
  • V3006 Objek telah dibuat tetapi tidak sedang digunakan. Kata kunci 'lempar' bisa hilang: lempar ArgumentException baru (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 278 (RecoveryServices)
  • V3006 Objek telah dibuat tetapi tidak sedang digunakan. Kata kunci 'lempar' bisa hilang: lempar ArgumentException baru (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 322 (RecoveryServices)
  • V3006 Objek telah dibuat tetapi tidak sedang digunakan. Kata kunci 'lempar' bisa hilang: lempar ArgumentException baru (FOO). PerbaruiAzureRmRecoveryServicesAsrProtectionDirection.cs 421 (RecoveryServices)
  • V3006 Objek telah dibuat tetapi tidak sedang digunakan. Kata kunci 'lempar' bisa hilang: lempar ArgumentException baru (FOO) PerbaruiAzureRmRecoveryServicesAsrProtectionDirection.cs 452 (RecoveryServices)

Ekspresi V3022 'apiType.HasValue' selalu salah. 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 ? // <= apiType.Value.ToString("g") : PsApiManagementApiType.Http.ToString("g"); } 

Logika kerja dilanggar. Jika apiType berisi nilai, maka kontrol tidak akan mencapai ekspresi kembali di akhir metode (semua cabang switch berisi pengembalian ). Jika tidak, metode ini akan selalu mengembalikan PsApiManagementApiType.Http.ToString ("g") , dan apiType.Value.ToString ("g") , masing-masing, tidak akan pernah dikembalikan.

Ekspresi V3022 'automationJob! = Null && automationJob == null' selalu salah. NodeConfigurationDeployment.cs 199 (Automation)

 public NodeConfigurationDeployment( ...., Management.Automation.Models.Job automationJob = null, ....) { .... if (automationJob != null && automationJob == null) return; .... } 

Kode paradoks. Dua cek yang saling bertentangan. Mungkin pemeriksaan kesetaraan nol kedua berisi variabel yang salah.

Ekspresi V3022 selalu salah. 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"); } .... } 

Memeriksa tidak ada gunanya, dan pengecualian tidak akan pernah dilempar. Kondisi ini membutuhkan persamaan simultan dari variabel linkedServiceType ke tiga nilai yang berbeda. Operator && dan || mungkin bingung. Kode yang diperbaiki:

 if (( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService || linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService || linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService) && (value == null || value.Length == 0)) .... 

Ekspresi V3022 'Ekus == null' selalu salah. PSKeyVaultCertificatePolicy.cs 129 (KeyVault)

 internal CertificatePolicy ToCertificatePolicy() { .... if (Ekus != null) { x509CertificateProperties.Ekus = Ekus == null ? null : new List<string>(Ekus); } .... } 

Pemeriksaan berlebihan variabel Ekus untuk kesetaraan nol . Mungkin tidak ada yang salah, tetapi kodenya terlihat jelek.

V3023 Pertimbangkan untuk memeriksa ungkapan ini. Ekspresi berlebihan atau mengandung kesalahan cetak. PolicyRetentionObjects.cs 207 (RecoveryServices)

 public virtual void Validate() { if (RetentionTimes == null || RetentionTimes.Count == 0 || RetentionTimes.Count != 1) { throw new ArgumentException( Resources.InvalidRetentionTimesInPolicyException); } } 

Pemeriksaan berlebihan, atau kondisi yang salah. Memeriksa RetentionTimes.Count == 0 tidak masuk akal, karena setelah itu periksa RetentionTimes.Count! = 1 .

V3025 Format salah. Jumlah item format yang berbeda diharapkan saat memanggil fungsi 'Format'. Argumen tidak digunakan: 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))) { .... } .... } 

Kesalahan dalam string format. Kualifikasi {0} digunakan dua kali, dengan dua argumen diteruskan ke metode Format . Opsi yang benar:

 if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {1}", this.Name, this.ResourceGroupName))) .... 

Kesalahan serupa lainnya:

  • V3025 Format salah. Jumlah item format yang berbeda diharapkan saat memanggil fungsi 'Format'. Argumen tidak digunakan: this.ResourceGroupName. RemoveScheduledQueryRuleCommand.cs 88 (Monitor)

V3042 Kemungkinan NullReferenceException. '?.' dan '.' operator digunakan untuk mengakses anggota objek 'imageAndOsType' VirtualMachineScaleSetStrategy.cs 81 (Hitung)

 internal static ResourceConfig<VirtualMachineScaleSet> CreateVirtualMachineScaleSetConfig(...., ImageAndOsType imageAndOsType, ....) { .... VirtualMachineProfile = new VirtualMachineScaleSetVMProfile { OsProfile = new VirtualMachineScaleSetOSProfile { ...., WindowsConfiguration = imageAndOsType.CreateWindowsConfiguration(), // <= ...., }, StorageProfile = new VirtualMachineScaleSetStorageProfile { ImageReference = imageAndOsType?.Image, // <= DataDisks = DataDiskStrategy.CreateVmssDataDisks( imageAndOsType?.DataDiskLuns, dataDisks) // <= }, }, .... } 

Saat membuat objek VirtualMachineScaleSetVMPile , variabel imageAndOsType digunakan tanpa memeriksa nol . Namun, saat membuat VirtualMachineScaleSetStorageProfile , variabel ini sudah diperiksa menggunakan operator akses bersyarat, dan dua kali. Kode terlihat tidak aman.

V3042 Kemungkinan NullReferenceException. '?.' dan '.' operator digunakan untuk mengakses anggota objek '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(....); // <= } .... } 

Seperti dalam kasus eksekusi normal, dan sebagai hasil dari penanganan pengecualian, variabel yang adaContacts bisa mendapatkan nol , setelah itu pekerjaan akan dilanjutkan. Lebih lanjut dalam kode variabel ini digunakan tanpa verifikasi.

V3066 Kemungkinan urutan argumen yang salah diteruskan ke metode 'PersistSyncServerRegistration': 'storageSyncServiceUid' dan 'discoveryUri'. EcsManagementInteropClient.cs 364 (StorageSync)

 public class EcsManagementInteropClient : IEcsManagement { .... public int PersistSyncServerRegistration(....) { return m_managementObject.PersistSyncServerRegistration( serviceUri, subscriptionId, storageSyncServiceName, resourceGroupName, clusterId, clusterName, storageSyncServiceUid, // <= discoveryUri, // <= serviceLocation, resourceLocation); } .... } 

Penganalisa curiga bahwa urutan argumen yang lewat ke metode PersistSyncServerRegistration bingung . Deklarasi Metode:

 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, MarshalAs(UnmanagedType.BStr)] string storageSyncServiceUid, // <= [In, MarshalAs(UnmanagedType.BStr)] string serviceLocation, [In, MarshalAs(UnmanagedType.BStr)] string resourceLocation); .... } 

Memang, ada sesuatu yang bercampur aduk di sini dengan argumen nomor tujuh dan delapan. Penulis perlu memverifikasi kode.

V3077 Setter properti 'GetGuid' tidak menggunakan parameter 'nilai'. RecoveryServicesBackupCmdletBase.cs 54 (RecoveryServices)

 public abstract class RecoveryServicesBackupCmdletBase : AzureRMCmdlet { .... static string _guid; protected static string GetGuid { get { return _guid; } set { _guid = Guid.NewGuid().ToString(); } } .... } 

Setter tidak menggunakan parameter yang dikirimkan. Sebagai gantinya, mereka mendapatkan GUID baru dan menetapkannya ke bidang _guid . Saya pikir sebagian besar pembaca akan setuju bahwa kode tersebut terlihat paling jelek. Menggunakan konstruksi semacam itu tidak mudah: untuk (kembali) menginisialisasi properti GetGuid , Anda harus memberinya nilai palsu, yang sama sekali tidak terlihat. Tetapi yang paling utama saya terhibur pada saat bagaimana penulis sendiri menggunakan konstruksi ini. Hanya ada satu tempat dalam kode tempat GetGuid bekerja . Lihatlah:

 public override void ExecuteCmdlet() { .... var itemResponse = ServiceClientAdapter.CreateOrUpdateProtectionIntent( GetGuid ?? Guid.NewGuid().ToString(), ....); .... } 

Hebat!

V3091 Analisis empiris. Mungkin salah ketik ada di dalam string literal: "Id Grup Manajemen." Kata 'Id' mencurigakan. Constants.cs 36 (Sumber)

 public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id"; // <= public const string Recurse = "Recursively list the children of the management group"; public const string ParentId = "Parent Id of the management group"; public const string GroupName = "Management Group Id"; // <= public const string DisplayName = "Display Name of the management group"; public const string Expand = "Expand the output to list the children of the management group"; public const string Force = "Force the action and skip confirmations"; public const string InputObject = "Input Object from the Get call"; public const string ParentObject = "Parent Object"; } 

Penganalisis menunjukkan kemungkinan kesalahan dalam string yang ditetapkan untuk konstanta GroupName . Kesimpulannya didasarkan pada analisis empiris penugasan lain dengan mempertimbangkan nama variabel akun. Saya pikir dalam hal ini analisanya benar, dan nilai konstanta GroupName haruslah "Nama Grup Manajemen". Kesalahan ini mungkin disebabkan oleh fakta bahwa nilai untuk konstanta GroupId disalin , tetapi mereka lupa untuk mengubahnya.

Kesalahan serupa lainnya:

  • V3091 Analisis empiris. Mungkin salah ketik ada di dalam string literal. Kata 'Nama' mencurigakan. ParamHelpMsgs.cs 153 (RecoveryServices)

V3093 The '|' operator mengevaluasi kedua operan. Mungkin hubungan arus pendek '||' Operator harus digunakan sebagai gantinya. PSKeyVaultCertificatePolicy.cs 114 (KeyVault)

 internal CertificatePolicy ToCertificatePolicy() { .... if (!string.IsNullOrWhiteSpace(SubjectName) || DnsNames != null || Ekus != null || KeyUsage != null | // <= ValidityInMonths.HasValue) { .... } .... } 

Ada kecurigaan bahwa telah terjadi kesalahan, dan operator || juga harus digunakan di antara kondisi terakhir di blok if . Jawaban yang tepat, seperti yang sering terjadi, hanya dapat diberikan oleh pengembang.

V3095 Objek 'sertifikat' digunakan sebelum diverifikasi terhadap nol. Periksa baris: 41, 43. CertificateInfo.cs 41 (Automation)

 public CertificateInfo( ...., Azure.Management.Automation.Models.Certificate certificate) { .... this.Name = certificate.Name; if (certificate == null) return; .... } 

Klasik Objek digunakan terlebih dahulu, dan hanya kemudian tautan diperiksa untuk null . Kami sangat sering menemukan kesalahan seperti itu. Pertimbangkan kesalahan serupa lainnya.

V3095 Objek 'clusterCred' digunakan sebelum diverifikasi terhadap nol. Periksa baris: 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) .... } 

Dan beberapa kesalahan serupa lainnya:

  • V3095 Objek '_profile' digunakan sebelum diverifikasi terhadap null. Periksa baris: 47, 49. RMProfileClient.cs 47 (Akun)
  • V3095 Objek 'this.LoadBalancer.BackendAddressPools' digunakan sebelum diverifikasi terhadap nol. Periksa baris: 56, 63. AddAzureRmLoadBalancerBackendAddressPoolConfigCommand.cs 56 (CognitiveServices)
  • Secara umum, dalam kode Azure PowerShell, saya bertemu lebih banyak kesalahan V3095 . Tapi mereka semua sangat mirip, jadi saya tidak akan membahas hal ini lebih detail.

V3125 Objek 'startTime' digunakan setelah diverifikasi terhadap nol. Periksa baris: 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)); // <= } .... if (lastModifiedTime.HasValue) { odataFilter.Add("properties/lastModifiedTime ge " + this.FormatDateTime(startTime.Value)); // <= } .... } 

Juga jenis kesalahan yang cukup umum. Variabel startTime diperiksa untuk nilai pada penggunaan pertama. Lain kali Anda menggunakan ini, jangan. Tapi itu bisa lebih buruk. Lihatlah blok if yang kedua. Saya berpikir bahwa seharusnya tidak ada variabel startTime sama sekali . Ini ditunjukkan oleh tidak adanya pemeriksaan untuk keberadaan nilai sebelum digunakan, dan string yang dibentuk untuk meneruskan ke metode Tambahkan . Bagian pertama dari baris ini menyebutkan variabel lain ( lastModifiedTime ).

V3125 Objek 'firstPage' digunakan setelah diverifikasi terhadap null. Periksa baris: 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)) // <= { .... } .... } 

Kesalahan jelas lainnya. Variabel firstPage digunakan dengan tidak aman, meskipun sebelumnya dalam kode ada penggunaan variabel ini dengan pemeriksaan awal untuk null .

V3125 dalam kode Azure PowerShell bahkan lebih sukses daripada V3095 yang dijelaskan sebelumnya. Semuanya juga dari tipe yang sama. Saya pikir kita dapat membatasi diri pada dua yang kita periksa.

V3137 Variabel 'apiVersionSetId' ditugaskan tetapi tidak digunakan pada akhir fungsi. 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)) // <= { WriteObject(....); } else { WriteObject(Client.GetApiVersionSet(...., ApiVersionSetId)) // <= } } 

Penganalisa melaporkan bahwa apiVersionSetId variabel lokal telah diinisialisasi, tetapi belum digunakan. Seringkali pola seperti itu menunjukkan kesalahan. Saya pikir dalam kasus ini probabilitas kesalahan tinggi, mengingat bahwa nama apiVersionSetId variabel lokal dan nama properti ApiVersionSetId hanya berbeda dalam kasus huruf pertama. Lihatlah kodenya. Setelah menginisialisasi apiVersionSetId (dengan satu atau lain cara), maka hanya properti ApiVersionSetId yang digunakan dalam kode. Sangat, sangat mencurigakan.

V3137 Variabel 'cacheId' ditugaskan tetapi tidak digunakan pada akhir fungsi. 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); // <= var actionWarning = string.Format(...., CacheId); // <= .... Client.CacheRemove(resourceGroupName, serviceName, CacheId); // <= .... } 

Situasi, hampir persis mengulangi yang sebelumnya dipertimbangkan. CacheId variabel lokal tidak digunakan setelah inisialisasi. Sebagai gantinya, mereka menggunakan properti dengan nama yang sangat mirip, CacheId . Saya tidak tahu, mungkin ini adalah pola di antara pengembang Azure PowerShell. Tapi itu terlihat seperti kesalahan.

V3143 Parameter 'nilai' ditulis ulang di dalam setter properti, dan tidak digunakan setelah itu. 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; } // <= } 

Bidang partnerType dinyatakan seperti ini:

 /// <summary> /// Default partner type. /// </summary> private string partnerType = "B2B"; 

Berlawanan dengan nama solusi di mana kesalahan ini terdeteksi (LogicApp), saya tidak melihat logika di sini. Menggunakan nilai dalam setter untuk merekam bukan kejadian langka, tetapi dalam kasus ini kita berbicara tentang kehilangan nilai aslinya. Terlihat aneh. Kode memiliki akses baca tunggal ke properti ini. Mungkin Anda harus mencari nasihat ahli lagi. Mungkin saya tidak mengerti sesuatu. Faktanya adalah bahwa saya bertemu beberapa pola yang sama persis:

  • V3143 Parameter 'nilai' ditulis ulang di dalam setter properti, dan tidak digunakan setelah itu. NewAzureIntegrationAccountSchemaCommand.cs 79 (LogicApp)
  • V3143 Parameter 'nilai' ditulis ulang di dalam setter properti, dan tidak digunakan setelah itu. NewAzureIntegrationAccountSchemaCommand.cs 87 (LogicApp)
  • V3143 Parameter 'nilai' ditulis ulang di dalam setter properti, dan tidak digunakan setelah itu. UpdateAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
  • V3143 Parameter 'nilai' ditulis ulang di dalam setter properti, dan tidak digunakan setelah itu. PerbaruiAzureIntegrationAccountSchemaCommand.cs 80 (LogicApp)
  • V3143 Parameter 'nilai' ditulis ulang di dalam setter properti, dan tidak digunakan setelah itu. PerbaruiAzureIntegrationAccountSchemaCommand.cs 88 (LogicApp)

Kesimpulan


Itu semua bug menarik yang ditemukan dalam kode Azure PowerShell.Penggemar dan hanya tertarik, saya sarankan melakukan studi independen tentang kesalahan dalam kode proyek ini (atau lainnya). Saya mungkin bisa melewatkan sesuatu yang menarik. Untuk melakukan ini, cukup unduh dan instal PVS-Studio .

Terima kasih sudah membaca. Kode tanpa kode!



Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Sergey Khrenov. Azure PowerShell: Kebanyakan Tidak Berbahaya .

Source: https://habr.com/ru/post/id470730/


All Articles