Kisah bagaimana PVS-Studio menemukan kesalahan di perpustakaan yang digunakan di ... PVS-Studio

Gambar 1

Ini adalah cerita pendek tentang bagaimana menggunakan PVS-Studio dimungkinkan untuk menemukan kesalahan dalam kode sumber perpustakaan yang digunakan dalam PVS-Studio. Selain itu, tidak teoretis, tetapi aktual - kesalahan itu diwujudkan dalam praktik ketika menggunakan perpustakaan di penganalisa.

Dalam PVS-Studio_Cmd (serta beberapa utilitas lainnya) kami menggunakan perpustakaan khusus untuk parsing argumen baris perintah - CommandLine.

Hari ini saya terlibat dalam mendukung mode baru dalam PVS-Studio_Cmd, dan kebetulan saya harus menggunakan perpustakaan argumen parsing ini. Dalam proses penulisan kode, saya juga men-debug-nya, karena saya harus bekerja dengan API yang tidak dikenal.

Jadi, kode tersebut ditulis, dikompilasi, dijalankan untuk dieksekusi, ii ...

Gambar 3


Eksekusi kode masuk ke pustaka tempat pengecualian tipe NullReferenceException terjadi . Dari samping itu tidak terlalu jelas - saya tidak memberikan referensi nol eksplisit apa pun ke metode ini.

Untuk berjaga-jaga, saya melihat komentar pada metode yang disebut. Sangat tidak mungkin bahwa mereka menggambarkan kondisi untuk pengecualian tipe NullReferenceException (karena biasanya, menurut saya, pengecualian dari tipe ini tidak terduga).

Gambar 2


Dalam komentar untuk metode ini, tidak ada informasi tentang NullReferenceException (yang, bagaimanapun, diharapkan).

Untuk melihat apa yang menyebabkan pengecualian (dan di mana), saya memutuskan untuk mengunduh kode sumber proyek, mengkompilasi dan menghubungkan versi debug perpustakaan ke penganalisis. Kode sumber untuk proyek tersedia di GitHub . Diperlukan Versi 1.9.71, karena justru jenis inilah yang sekarang digunakan dalam penganalisa.

Saya memuat versi yang sesuai dari kode sumber, mengumpulkan, menghubungkan perpustakaan debug ke penganalisa, menjalankan kode untuk eksekusi dan melihat:

Gambar 4


Jadi, tempat pengecualiannya jelas - helpInfo adalah null , yang memunculkan pengecualian tipe NullReferenceException saat mengakses properti instance Kiri .

Dan kemudian saya menjadi bijaksana. Baru-baru ini, PVS-Studio untuk C # telah ditingkatkan dengan baik di berbagai bidang, termasuk di bidang pencarian referensi referensi yang berpotensi nol. Secara khusus, analisis antar prosedur ditingkatkan. Oleh karena itu, segera menjadi menarik bagi saya untuk memeriksa kode sumber untuk melihat apakah PVS-Studio dapat menemukan kesalahan yang sedang dibahas.

Saya memeriksa kode sumber, dan di antara peringatan lainnya, saya melihat persis apa yang saya harapkan.

Peringatan PVS-Studio : V3080 Kemungkinan ada null dereference di dalam metode di 'helpInfo.Left'. Pertimbangkan untuk memeriksa argumen 2: helpInfo. Parser.cs 405

Ya itu dia! Apa yang Anda butuhkan. Mari kita lihat kode sumber lebih terinci.

private bool DoParseArgumentsVerbs( string[] args, object options, ref object verbInstance) { var verbs = ReflectionHelper.RetrievePropertyList<VerbOptionAttribute>(options); var helpInfo = ReflectionHelper.RetrieveMethod<HelpVerbOptionAttribute>(options); if (args.Length == 0) { if (helpInfo != null || _settings.HelpWriter != null) { DisplayHelpVerbText(options, helpInfo, null); // <= } return false; } .... } 

Penganalisis menghasilkan pesan peringatan saat memanggil metode DisplayHelpVerbText dan memperingatkan tentang argumen kedua - helpInfo . Perhatikan bahwa metode ini ada di cabang pernyataan if . Ekspresi bersyarat tersusun sedemikian rupa sehingga cabang kemudian dapat dieksekusi dengan nilai-nilai variabel berikut:

  • helpInfo == null ;
  • _settings.HelpWriter! = null ;

Mari kita lihat isi metode DisplayHelpVerbText :

 private void DisplayHelpVerbText( object options, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb) { string helpText; if (verb == null) { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, null, out helpText); } else { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, verb, out helpText); } if (_settings.HelpWriter != null) { _settings.HelpWriter.Write(helpText); } } 

Karena kata kerja == null (lihat pemanggilan metode), kami tertarik pada cabang saat itu dari pernyataan if . Meskipun situasi dengan cabang lain akan serupa, kami akan mempertimbangkan cabang saat itu, karena dalam kasus khusus kami eksekusi melalui itu. Ingat bahwa helpInfo bisa menjadi nol .

Sekarang mari kita lihat isi metode HelpVerbOptionAttribute.InvokeMethod . Sebenarnya, Anda sudah melihatnya di screenshot di atas:

 internal static void InvokeMethod( object target, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb, out string text) { text = null; var method = helpInfo.Left; if (!CheckMethodSignature(method)) { throw new MemberAccessException( SR.MemberAccessException_BadSignatureForHelpVerbOptionAttribute .FormatInvariant(method.Name)); } text = (string)method.Invoke(target, new object[] { verb }); } 

helpInfo.Left disebut tanpa syarat, meskipun helpInfo bisa menjadi nol . Penganalisa memperingatkan tentang ini, dan ini terjadi.

Kesimpulan

Ternyata lucu bahwa dengan bantuan PVS-Studio dimungkinkan untuk menemukan kesalahan dalam kode perpustakaan yang digunakan dalam PVS-Studio. Saya pikir ini adalah semacam kelanjutan dari jawaban untuk pertanyaan "Apakah PVS-Studio menemukan kesalahan dalam kode PVS-Studio?". :) Ini dapat menemukan kesalahan tidak hanya dalam kode PVS-Studio, tetapi juga dalam kode perpustakaan yang digunakan.

Akhirnya, saya mengusulkan untuk mengunduh alat analisis dan mencoba memeriksa proyek Anda - bagaimana jika Anda dapat menemukan sesuatu yang menarik di sana juga?



Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Sergey Vasiliev. Kisah bagaimana PVS-Studio menemukan kesalahan di perpustakaan yang digunakan di ... PVS-Studio

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


All Articles