10 Bug Top Ditemukan di Proyek C # pada tahun 2019

Gambar 1

Hai untuk semua penggemar bug! Tahun Baru akan segera tiba, jadi sekarang saatnya untuk mencatat tahun yang akan datang. Secara tradisi, kami senang menyajikan daftar kesalahan teratas yang ditemukan oleh tim PVS-Studio di proyek C # terbuka pada tahun 2019. Siap? Kalau begitu mari kita pergi.

Tempat kesepuluh "Menipu semua orang"


V3066 Kemungkinan urutan argumen yang salah diteruskan ke metode 'AdjustCellBorderStyle': 'isFirstDisplayedRow' dan 'isFirstDisplayedColumn'. DataGridViewComboBoxCell.cs 1934

protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { .... dgvabsEffective = AdjustCellBorderStyle( DataGridView.AdvancedCellBorderStyle, dgvabsPlaceholder, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedRow, // <= isFirstDisplayedColumn); // <= .... } 

Kesalahan dari artikel " WinForms: Errors, Holmes ". Penganalisa menunjukkan bahwa ketika dua argumen terakhir dari metode ini digabungkan. Mari kita lihat deklarasi AdjustCellBorderStyle :

 public virtual DataGridViewAdvancedBorderStyle AdjustCellBorderStyle( DataGridViewAdvancedBorderStyledataGridViewAdvancedBorderStyleInput, DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { .... } 

Sepertinya penganalisisnya benar. Seringkali pengembang dengan sengaja memberikan beberapa argumen dalam urutan terbalik, misalnya, untuk bertukar variabel. Tapi sepertinya bukan itu masalahnya. Pertama, variabel tipe bool digabungkan. Kedua, tidak ada nama metode yang tidak biasa: tidak ada "Swap" atau "Reverse". Selain itu, tidak sulit untuk membuat kesalahan seperti ini: orang-orang memandang secara berbeda urutan susunan "baris / kolom".

Tempat kesembilan "Sangat dekat dengan keabadian"


V3110 Kemungkinan rekursi tak terbatas di dalam metode 'TryValidateModel'. PrefixedModuleUpdater.cs 48

 public bool TryValidateModel(object model, string prefix) { return TryValidateModel(model, Prefix(prefix)); } 

Kesalahan dari artikel " Memindai kode Orchard CMS for Bugs ". Ada kesalahan yang menyebabkan rekursi tak terbatas. Untuk memahami cara kesalahan dibuat, kita harus mempertimbangkan kelebihan metode TryValidateModel :

 public bool TryValidateModel(object model) { return _updateModel.TryValidateModel(model); } 

Kemungkinan kasus pertama juga harus menggunakan panggilan seperti itu:

 public bool TryValidateModel(object model, string prefix) { return _updateModel.TryValidateModel(model, Prefix(prefix)); } 

Kode berhasil dikompilasi, karena _updateModel adalah tipe IUpdateModel dan kelas saat ini juga mengimplementasikan antarmuka IUpdateModel .

Tempat kedelapan "Temukan saya jika Anda bisa"


V3091 Analisis empiris. Mungkin salah ketik ada di dalam string literal: "Id Grup Manajemen." Kata 'Id' mencurigakan. 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"; // <= 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"; } 

Kesalahan dari artikel " Azure PowerShell: Mostly Harmless ". Penganalisa menduga konstanta GroupName diinisialisasi dengan string yang salah. Mungkin harus ada sesuatu seperti "Nama Grup Manajemen" . Kekritisan kesalahan ini masih dipertanyakan, tetapi kesalahannya jelas jarang dan sulit dideteksi.

Tempat ketujuh "Baru saja diabaikan"


V3078 Urutan penyortiran asli akan hilang setelah panggilan berulang ke metode 'OrderBy'. Gunakan metode 'ThenBy' untuk mempertahankan penyortiran asli. 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)); } } 

Kesalahan dari artikel " Memeriksa Telerik UI untuk UWP sebagai Cara Memulai dengan PVS-Studio ." Hasil pengurutan sebelumnya akan hilang karena panggilan berulang ke OrderBy pada koleksi yang sudah diurutkan. Kita harus menggunakan ThenBy dalam hal ini:

 this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line)); 

Kesalahan semacam itu dilakukan karena kurang perhatian atau ketidaktahuan. Saya pikir copy-paste yang harus disalahkan di sini.

Tempat keenam "Kode didokumentasikan", kata mereka


V3009 Aneh bahwa metode ini selalu mengembalikan satu dan nilai yang sama dari 'benar'. MaskedTextProvider.cs 1529

 public bool Remove(out int testPosition, out MaskedTextResultHint resultHint) { .... if (lastAssignedPos == INVALID_INDEX) { .... return true; // nothing to remove. } .... return true; } 

Kesalahan dari artikel " Memeriksa .NET Core Libraries Source Code oleh PVS-Studio Static Analyzer ". Metode ini akan selalu mengembalikan true . Ya, ini sebuah kesalahan, tetapi ada hal lain yang sangat aneh. Metode ini diikuti oleh komentar terperinci:

Menghapus karakter terakhir dari string yang diformat. (Hapus karakter terakhir dalam string virtual). Saat keluar, param keluar berisi posisi di mana operasi sebenarnya dilakukan. Posisi ini relatif terhadap string uji. Parameter MaskedTextResultHint out memberikan informasi lebih lanjut tentang hasil operasi. Mengembalikan nilai true pada kesuksesan, false sebaliknya.

Perhatikan kalimat terakhir. Siapa yang bahkan membaca komentar ini? Namun demikian, jika kita menanggapinya dengan serius, kesalahan seperti itu mudah disindir, misalnya, selama refactoring atau debugging. Nah, penulis ingin memeriksa varian ketika hasil metode selalu benar, tetapi lupa untuk mengembalikan semuanya seperti semula.

Tempat kelima "Indeks saya, sekarang!"


V3102 Akses mencurigakan ke elemen objek 'seq' dengan indeks konstan di dalam satu loop. 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; } 

Kesalahan dari artikel " Memeriksa .NET Core Libraries Source Code oleh PVS-Studio Static Analyzer ". Ketika melintasi koleksi seq dalam for loop, pengembang secara keliru menggunakan akses hanya ke elemen pertama di semua iterasi (indeks 0 bukan i ).

Tempat keempat "Hanya satu dolar pendek"


V3138 String literal berisi ekspresi potensial yang diinterpolasi. Pertimbangkan untuk memeriksa: 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}"); } } } 

Kesalahan dari artikel " Memeriksa .NET Core Libraries Source Code oleh PVS-Studio Static Analyzer ". Rupanya, string "Mencoba untuk melempar: {e}" harus diinterpolasi. Karena $ karakter tidak terjawab, representasi garis dari pengecualian e tidak akan dimasukkan ke dalam string. Akibatnya, garis akan digunakan "sebagaimana adanya."

Tempat ketiga "Tidak ada jalan keluar"


V3008 [CWE-563] Variabel 'this.linker.s3.region' diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 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; } } 

Kesalahan dari artikel " Mencari kesalahan dalam kode sumber SDK Layanan Web Amazon untuk .NET ". Pengembalian terlewatkan di badan blok if . Akibatnya, variabel this.linker.s3.region akan selalu mendapatkan nilai, termasuk baris kosong dan nol.

Posisi kedua "Gaun yang tepat!"


V3070 Variabel tidak diinisialisasi 'LANG_USER_DEFAULT' digunakan ketika menginisialisasi variabel '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); .... } 

Kesalahan dari artikel " WinForms: Errors, Holmes ". Urutan inisialisasi bidang kelas bingung. Untuk menghitung nilai bidang LOCALE_USER_DEFAULT , bidang LANG_USER_DEFAULT digunakan, yang belum diinisialisasi saat ini dan 0. Variabel tidak digunakan di mana pun lebih jauh dalam kode. Untuk mendapatkan apa yang menyebabkan kesalahan ini, seluruh program uji yang berisi metode dari kode WinForms ditulis. Alih-alih beberapa konstanta yang digunakan, nilai aktualnya diganti dengan kesederhanaan:

 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); } } 

Sebagai hasil dari eksekusi kita akan memiliki yang berikut: 0. Sekarang mari kita perbaiki kesalahan dengan menukar deklarasi bidang LOCALE_USER_DEFAULT dan LANG_USER_DEFAULT . Hasil pelaksanaan program: 1024.

Tempat pertama "Percobaan pertama, lalu percaya"


Tidak pernah mudah dengan tempat pertama. Pasti ada sesuatu yang luar biasa dan menawan di sini. Awalnya, untuk artikel ini saya memilih lebih dari dua puluh kesalahan menarik, tetapi tidak ada yang layak dari tempat pertama di antara mereka. Saat itulah saya mengingat artikel rekan saya, Sergey Vasiliev. Artikel ini hanya menjelaskan satu kesalahan saja. Keindahan kesalahan ini adalah bahwa hal itu secara langsung mempengaruhi pekerjaan penganalisa kami. Bagaimana? Anda sudah bisa mendapatkannya dari judul artikel: " Kisah bagaimana PVS-Studio menemukan kesalahan di perpustakaan yang digunakan di ... PVS-Studio ". Di sinilah saya merasa terlalu malas untuk memberikan deskripsi kesalahan dan dengan demikian akan menyarankan Anda mengikuti tautan dan mencari tahu detailnya. :) Saya jamin itu layak. Apalagi artikelnya pendek.

Kesimpulan


Saya harap kesalahannya luar biasa untuk Anda dan artikelnya tidak melelahkan. Sebagai catatan, Anda selalu dapat mengunduh penganalisa PVS-Studio untuk menemukan bug di proyek pihak ketiga dan Anda untuk menyenangkan diri sendiri, kolega, dan Tom, Dick, atau Harry. Biarkan kesalahan kurang, dan waktu untuk perbaikan diri - lebih banyak! :)

Apakah Anda membaca sampai akhir? Selamat saya untuk mencapai level baru! Jangan lewatkan artikel terbaru kami di blog kami - bug terbaik di proyek Java dan C ++ ditemukan pada 2019.

Gambar 2

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


All Articles