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

Gambar 1

Ini adalah cerita pendek tentang bagaimana PVS-Studio membantu kami menemukan kesalahan dalam kode sumber perpustakaan yang digunakan dalam PVS-Studio. Dan itu bukan kesalahan teoretis tetapi kesalahan aktual - kesalahan muncul dalam praktik saat menggunakan perpustakaan di penganalisa.

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

Hari ini saya mendukung mode baru dalam PVS-Studio_Cmd dan kebetulan saya harus menggunakan perpustakaan ini untuk parsing argumen baris perintah. Saat menulis kode, saya juga men-debug-nya karena saya harus bekerja dengan API yang tidak dikenal.

Jadi, kode tersebut ditulis, dikompilasi, dieksekusi dan ...

Gambar 3

Eksekusi kode masuk ke dalam pustaka tempat pengecualian tipe NullReferenceException terjadi. Tidak begitu jelas dari samping - Saya tidak memberikan referensi nol ke dalam metode ini.

Yang pasti, saya melihat komentar pada metode callee. Hampir tidak mungkin bahwa mereka menggambarkan kondisi terjadinya pengecualian dari tipe NullReferenceException (seperti yang tampak bagi saya biasanya pengecualian dari tipe ini tidak disediakan untuk).

Gambar 2

Tidak ada informasi tentang NullReferenceException di komentar ke metode (yang, bagaimanapun, diharapkan).

Untuk melihat apa yang menyebabkan pengecualian (dan di mana itu terjadi), saya memutuskan untuk mengunduh kode sumber proyek, membangunnya dan menambahkan referensi ke versi debug perpustakaan ke penganalisis. Kode sumber proyek tersedia di GitHub . Kami membutuhkan versi 1.9.71 perpustakaan. Ini adalah yang digunakan dalam analisa sekarang.

Saya mengunduh versi kode sumber yang sesuai, membangun perpustakaan, menambahkan referensi ke perpustakaan debug ke penganalisa, menjalankan kode dan melihat:

Gambar 4

Jadi, tempat pengecualian terjadi jelas - helpInfo memiliki nilai nol , yang menyebabkan pengecualian tipe NullReferenceException saat mengakses properti Kiri .

Saya mulai memikirkannya. Baru-baru ini, PVS-Studio untuk C # telah ditingkatkan dengan baik dalam berbagai aspek, termasuk pencarian referensi referensi yang berpotensi nol. Secara khusus, analisis antar-prosedur ditingkatkan dalam beberapa cara. Itu sebabnya saya langsung tertarik untuk memeriksa kode sumber untuk memahami jika PVS-Studio dapat menemukan kesalahan yang sedang dibahas.

Saya memeriksa kode sumber dan di antara peringatan lain 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, ini dia! Itulah yang kita butuhkan. Mari kita lihat lebih detail kode sumbernya.

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 mengeluarkan peringatan untuk memanggil metode DisplayHelpVerbText dan memperingatkan tentang argumen kedua - helpInfo . Perhatikan bahwa metode ini terletak di cabang pernyataan if . Ekspresi bersyarat tersusun sedemikian rupa sehingga cabang saat itu dapat dieksekusi pada nilai variabel berikutnya:

  • 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 selanjutnya dari pernyataan if . Meskipun situasinya mirip dengan cabang lain , mari kita pertimbangkan cabang kemudian karena dalam kasus khusus kami eksekusi melewatinya. Ingat bahwa helpInfo mungkin nol .

Sekarang mari kita lihat isi HelpVerbOptionAttribute . Metode InvokeMethod . Sebenarnya, Anda sudah melihatnya pada tangkapan layar 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, sedangkan helpInfo mungkin nol . Penganalisa memperingatkan tentang hal itu, dan itulah yang terjadi.

Kesimpulan

Sangat menyenangkan bahwa kami berhasil menemukan kesalahan dalam kode sumber perpustakaan yang digunakan dalam PVS-Studio dengan bantuan PVS-Studio. Saya pikir ini adalah semacam jawaban untuk pertanyaan "Apakah PVS-Studio menemukan kesalahan dalam kode sumber PVS-Studio?". :) Penganalisa dapat menemukan kesalahan tidak hanya dalam kode PVS-Studio tetapi juga dalam kode perpustakaan yang digunakan.

Akhirnya, saya sarankan Anda mengunduh penganalisa dan mencoba memeriksa proyek Anda - bagaimana jika Anda dapat menemukan sesuatu yang menarik di sana juga?

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


All Articles