Analisis kode warisan ketika kode sumber hilang: untuk dilakukan atau tidak dilakukan? Penerapan analisis statis dalam pengembangan perangkat lunak Deteksi kesalahan dini untuk mengurangi biaya pengembangan

Artikel asli dapat ditemukan menggunakan Wayback Machine - Internet Archive: Static Code Analysis.

Karena semua artikel di situs kami disajikan dalam bahasa Rusia dan Inggris, kami telah menerjemahkan artikel Analisis Kode Statis ke dalam bahasa Rusia. Dan pada saat yang sama kami memutuskan untuk mempublikasikannya di Habré. Sebuah menceritakan kembali artikel ini telah diterbitkan di sini. Tapi saya yakin banyak yang akan tertarik membaca terjemahannya.

Prestasi terpentingnya sebagai programmer untuk tahun-tahun terakhir Saya menganggap kenalan dengan metode analisis kode statis dan aplikasi aktifnya. Ini bukan tentang ratusan bug serius yang dijauhkan dari kode berkat dia, tetapi tentang perubahan yang dibawa oleh pengalaman ini dalam pandangan dunia programmer saya sehubungan dengan masalah keandalan dan kualitas perangkat lunak.

Harus segera dicatat bahwa segala sesuatu tidak dapat direduksi menjadi kualitas, dan mengakui ini tidak berarti mengkhianati prinsip moral Anda. Nilai memiliki produk yang Anda buat secara keseluruhan, dan kualitas kode hanyalah salah satu komponennya bersama dengan biaya, fungsionalitas, dan karakteristik lainnya. Dunia tahu banyak proyek game yang sangat sukses dan dihormati, diisi dengan bug dan jatuh tanpa henti; dan akan bodoh untuk mendekati menulis permainan dengan keseriusan yang sama dengan yang mereka buat perangkat lunak untuk pesawat ulang-alik. Namun, kualitas tidak diragukan lagi merupakan komponen penting.

Saya selalu mencoba untuk menulis kode yang baik. Secara alami, saya seperti seorang pengrajin yang didorong oleh keinginan untuk terus meningkatkan sesuatu. Saya membaca tumpukan buku dengan judul bab yang membosankan seperti Strategi, Standar, dan Rencana Kualitas, dan bekerja di Armadillo Aerospace membuka pintu saya ke dunia pengembangan perangkat lunak yang sama sekali berbeda dengan peningkatan persyaratan untuk keamanan.

Lebih dari sepuluh tahun yang lalu, ketika kami mengembangkan Quake 3, saya membeli lisensi untuk PC-Lint dan mencoba menggunakannya dalam pekerjaan saya: gagasan tentang deteksi cacat otomatis dalam kode menarik saya. Namun, kebutuhan untuk menjalankan dari baris perintah dan melihat daftar panjang pesan diagnostik membuat saya enggan menggunakan alat ini, dan saya segera meninggalkannya.

Sejak itu, baik jumlah pemrogram maupun ukuran basis kode telah bertambah besar, dan penekanan dalam pemrograman telah bergeser dari C ke C++. Semua ini telah menyiapkan lahan yang jauh lebih subur untuk bug perangkat lunak. Beberapa tahun yang lalu, setelah membaca pilihan artikel ilmiah tentang analisis kode statis modern, saya memutuskan untuk memeriksa bagaimana hal-hal telah berubah di bidang ini selama sepuluh tahun terakhir sejak saya mencoba bekerja dengan PC-Lint.

Pada saat itu, kode kami dikompilasi pada peringatan tingkat ke-4, sementara kami hanya membiarkan beberapa diagnostik yang sangat khusus dimatikan. Dengan pendekatan ini - dengan sengaja memperlakukan setiap peringatan sebagai kesalahan - programmer dipaksa untuk secara ketat mematuhi kebijakan ini. Dan meskipun kode kami dapat menemukan beberapa sudut berdebu di mana segala macam "sampah" telah menumpuk selama bertahun-tahun, secara umum itu cukup modern. Kami pikir kami memiliki basis kode yang cukup bagus.

Kerahasiaan

Semuanya dimulai dengan fakta bahwa saya menghubungi Coverity dan mendaftar untuk uji coba diagnostik kode kami dengan alat mereka. Ini adalah program yang serius, biaya lisensi tergantung pada jumlah baris kode, dan kami menetapkan harga lima digit. Saat menunjukkan kepada kami hasil analisis, para ahli dari Coverity mencatat bahwa database kami adalah salah satu yang terbersih dalam "kategori berat" yang pernah mereka lihat (mungkin mereka mengatakan ini kepada semua klien untuk menghibur mereka), tetapi laporan tersebut yang mereka serahkan kepada kami, berisi sekitar seratus bidang masalah. Pendekatan ini sangat berbeda dari pengalaman saya sebelumnya dengan PC-Lint. Rasio signal-to-noise dalam kasus ini ternyata sangat tinggi: sebagian besar peringatan yang dikeluarkan oleh Coverity memang menunjukkan bagian kode yang salah yang dapat memiliki konsekuensi serius.

Kejadian ini benar-benar membuka mata saya untuk analisis statis, tetapi harga tinggi dari semua kesenangan membuat saya tidak membeli alat untuk beberapa waktu. Kami berpikir bahwa dalam kode yang tersisa sebelum rilis, kami tidak akan memiliki banyak kesalahan.

Microsoft /analisis

Ada kemungkinan bahwa saya akhirnya akan memutuskan untuk membeli Coverity, tetapi ketika saya memikirkannya, Microsoft menghentikan keraguan saya dengan menerapkan fitur /analisis baru di 360 SDK. /Analyze dulu tersedia sebagai komponen dari Visual Studio versi mahal yang gila-gilaan, dan kemudian tiba-tiba gratis untuk setiap pengembang xbox 360. Seperti yang saya pahami, tentang kualitas game di 360th Platform Microsoft lebih peduli tentang kualitas perangkat lunak di bawah Windows. :-)

Dari sudut pandang teknis, penganalisis Microsoft hanya melakukan analisis lokal, mis. itu lebih rendah dari analisis global Coverity, namun, ketika kami menyalakannya, itu jatuh pegunungan pesan - lebih dari yang diberikan Coverity. Ya, ada banyak kesalahan positif, tetapi bahkan tanpa itu ada banyak serangga yang menakutkan dan sangat menyeramkan.

Saya perlahan mulai mengedit kode - pertama-tama, saya mengurus sendiri, lalu sistem, dan akhirnya game. Saya harus bekerja dengan baik dan mulai di waktu luang saya, sehingga seluruh proses berlangsung selama beberapa bulan. Namun, penundaan ini juga memiliki efek samping yang menguntungkan: kami memastikan bahwa /analyze memang menangkap cacat penting. Faktanya adalah bahwa bersamaan dengan suntingan saya, pengembang kami melakukan perburuan bug multi-hari yang besar, dan ternyata setiap kali mereka menyerang jejak beberapa kesalahan, sudah ditandai / dianalisis, tetapi belum diperbaiki oleh saya. Selain itu, ada kasus lain yang tidak terlalu dramatis, di mana debugging mengarahkan kita ke kode yang sudah ditandai dengan /analyze. Ini semua adalah kesalahan nyata.

Pada akhirnya, saya mendapatkan semua kode yang saya gunakan untuk mengkompilasi ke executable 360 ​​tanpa satu peringatan dengan /analyze diaktifkan, dan mengatur mode kompilasi ini sebagai default untuk 360 build. Setelah itu, kode setiap programmer yang bekerja pada platform yang sama diperiksa kesalahannya setiap kali dikompilasi, sehingga ia dapat segera memperbaiki bug saat mereka diperkenalkan ke dalam program, daripada saya harus menanganinya nanti. Tentu saja, ini sedikit memperlambat kompilasi, tetapi /analyze sejauh ini merupakan alat tercepat yang pernah saya gunakan, dan percayalah, itu sepadan.

Suatu kali, dalam beberapa proyek, kami secara tidak sengaja mematikan analisis statis. Beberapa bulan berlalu dan ketika saya melihat ini dan menyalakannya kembali, alat itu mengeluarkan banyak peringatan kesalahan baru yang diperkenalkan ke kode pada waktu itu. Demikian pula, pemrogram yang hanya bekerja di PC atau PS3 menyumbangkan kode buggy ke repositori dan tetap tidak mengetahuinya sampai mereka menerima email dengan laporan "gagal 360 build". Contoh-contoh ini dengan jelas menunjukkan bahwa dalam aktivitas sehari-hari mereka, pengembang membuat beberapa jenis kesalahan berulang-ulang, dan /analyze menyelamatkan kita dari kebanyakan kesalahan tersebut.

Studio PVS

Karena kami hanya dapat menggunakan /menganalisis pada kode 360, sejumlah besar basis kode kami masih belum tercakup oleh analisis statis - kode ini terkait untuk platform PC dan PS3, serta semua program yang hanya berjalan di PC.

Alat berikutnya yang saya kenal adalah PVS-Studio . Ini terintegrasi dengan mulus ke dalam Visual Studio dan menawarkan mode demo yang praktis (coba sendiri!). Dibandingkan dengan /analyze, PVS-Studio sangat lambat, tetapi berhasil menangkap sejumlah bug kritis baru, bahkan dalam kode yang sudah sepenuhnya dibersihkan dari sudut pandang /analyze. Selain kesalahan yang jelas, PVS-Studio menangkap banyak cacat lainnya, yang merupakan klise pemrograman yang salah, bahkan jika itu tampak seperti kode normal pada pandangan pertama. Karena itu, persentase tertentu dari positif palsu hampir tidak dapat dihindari, tetapi, sial, pola seperti itu ditemukan dalam kode kami, dan kami memperbaikinya.

Di situs web PVS-Studio Anda dapat menemukan sejumlah besar artikel bagus tentang alat ini, dan banyak di antaranya berisi contoh dari proyek sumber terbuka nyata yang mengilustrasikan jenis kesalahan yang tepat dari artikel tersebut. Saya berpikir untuk memasukkan di sini beberapa pesan diagnostik indikatif yang dikeluarkan oleh PVS-Studio, tetapi lebih banyak lagi yang telah muncul di situs. contoh menarik. Jadi kunjungi halamannya dan lihat sendiri. Dan ya - ketika Anda membaca contoh-contoh ini, jangan menyeringai dan mengatakan bahwa Anda tidak akan pernah menulis seperti itu.

Lint PC

Pada akhirnya, saya kembali ke opsi untuk menggunakan PC-Lint bersama dengan Visual Lint untuk diintegrasikan ke dalam lingkungan pengembangan. Dalam tradisi legendaris dunia Unix, alat ini dapat dikonfigurasi untuk melakukan hampir semua tugas, tetapi antarmukanya tidak terlalu ramah pengguna dan Anda tidak bisa hanya "mengambil dan menjalankannya". Saya membeli satu set lima lisensi, tetapi sangat sulit untuk menguasainya sehingga, sejauh yang saya tahu, semua pengembang lain akhirnya meninggalkannya. Fleksibilitas memang memiliki kelebihan - misalnya, saya dapat mengaturnya untuk menguji semua kode kami untuk platform PS3, meskipun ini membutuhkan banyak waktu dan tenaga.

Dan lagi, kesalahan penting baru ditemukan dalam kode, yang sudah bersih dari sudut pandang /analisis dan PVS-Studio. Sejujurnya saya mencoba membersihkannya agar seratnya juga tidak menyumbat, tetapi tidak berhasil. Saya memperbaiki semua kode sistem, tetapi menyerah ketika saya melihat berapa banyak peringatan yang dia berikan pada kode permainan. Saya mengurutkan kesalahan ke dalam kelas dan menangani yang paling kritis, mengabaikan banyak kesalahan lain yang lebih terkait dengan kekurangan gaya atau masalah potensial.

Saya percaya bahwa upaya untuk memperbaiki sejumlah besar kode secara maksimal dari sudut pandang PC-Lint jelas akan gagal. Saya menulis beberapa kode dari awal di tempat-tempat di mana saya dengan patuh mencoba untuk menyingkirkan setiap komentar "serat" yang mengganggu, tetapi untuk sebagian besar programmer C / C ++ yang berpengalaman, pendekatan penanganan kesalahan ini sudah terlalu banyak. Saya masih harus mengutak-atik pengaturan PC-Lint untuk menemukan rangkaian peringatan yang paling tepat dan mendapatkan hasil maksimal dari alat ini.

kesimpulan

Saya belajar banyak dari semua ini. Saya khawatir beberapa kesimpulan saya akan sulit bagi orang-orang yang tidak harus secara pribadi melalui ratusan laporan bug dalam waktu singkat dan merasa sakit setiap kali mereka mulai mengeditnya, dan reaksi standar terhadap kata-kata saya adalah " baik, kami memiliki - tidak apa-apa" atau "tidak terlalu buruk".

Langkah pertama di sepanjang jalan adalah dengan jujur ​​mengakui pada diri sendiri bahwa kode Anda penuh dengan bug. Bagi sebagian besar programmer, ini adalah pil pahit yang harus ditelan, tetapi tanpa menelannya, Anda pasti akan melihat proposal apa pun untuk mengubah dan meningkatkan kode dengan jengkel, jika bukan permusuhan yang tidak terselubung. Kamu harus ingin mengkritik kode Anda.

Otomasi diperlukan. Ketika Anda melihat laporan kegagalan mengerikan dalam sistem otomatis, tidak mungkin untuk tidak mengalami kesombongan seperti itu, tetapi untuk setiap kesalahan dalam otomatisasi, ada banyak kesalahan manusia. Panggilan untuk "kode yang lebih baik," niat baik untuk lebih banyak sesi tinjauan kode, pemrograman berpasangan, dan sebagainya tidak berhasil, terutama ketika lusinan orang terlibat dalam sebuah proyek dan pekerjaan sedang terburu-buru. Nilai besar dari analisis statis terletak pada kemungkinan setiap kali Anda mulai temukan setidaknya sebagian kecil kesalahan yang dapat diakses oleh teknik ini.

Saya perhatikan bahwa dengan setiap pembaruan, PVS-Studio menemukan semakin banyak kesalahan dalam kode kami berkat diagnostik baru. Dari sini kita dapat menyimpulkan bahwa ketika basis kode mencapai ukuran tertentu, tampaknya memulai semua kesalahan yang diizinkan dari sudut pandang sintaksis. Dalam proyek besar, kualitas kode mengikuti pola statistik yang sama dengan sifat fisik materi - cacat di dalamnya ada di mana-mana, dan Anda hanya dapat mencoba meminimalkan dampaknya pada pengguna.

Alat analisis statis harus bekerja "dengan satu tangan terikat di belakang mereka": mereka harus menarik kesimpulan berdasarkan penguraian bahasa yang tidak selalu memberikan informasi untuk kesimpulan seperti itu, dan secara umum membuat asumsi yang sangat hati-hati. Oleh karena itu, Anda harus membantu parser Anda sebanyak mungkin - mendukung pengindeksan daripada aritmatika pointer, menyimpan grafik panggilan dalam satu file sumber, menggunakan anotasi eksplisit, dan seterusnya. Segala sesuatu yang mungkin tampak tidak jelas bagi penganalisis statis hampir pasti akan membingungkan sesama programmer Anda juga. Keengganan "peretas" yang khas terhadap bahasa dengan pengetikan statis yang ketat ("bahasa perbudakan dan disiplin") sebenarnya ternyata picik: kebutuhan proyek besar dan berumur panjang yang melibatkan tim besar programmer pada dasarnya berbeda dari tugas-tugas kecil dan cepat yang dilakukan untuk diri sendiri.

Pointer null adalah masalah terbesar di C/C++, setidaknya di sini. Kemungkinan penggunaan ganda dari satu nilai sebagai flag dan alamat menyebabkan jumlah kesalahan kritis yang luar biasa. Oleh karena itu, bila memungkinkan, C++ harus lebih menyukai referensi daripada pointer. Meskipun referensi "benar-benar" tidak lebih dari penunjuk yang sama, itu terikat oleh kewajiban implisit bahwa itu tidak boleh nol. Periksa pointer untuk null ketika mereka berubah menjadi referensi - ini akan memungkinkan Anda untuk melupakan masalah ini nanti. Ada banyak pola pemrograman yang mendarah daging dan berpotensi berbahaya dalam pembuatan game, tetapi saya tidak tahu cara untuk sepenuhnya dan tanpa rasa sakit berpindah dari cek nol ke referensi.

Masalah terpenting kedua dalam basis kode kami adalah bug dengan fungsi printf. Itu lebih diperparah oleh fakta bahwa melewati idStr alih-alih idStr::c_str() hampir setiap kali berakhir dengan crash program. Namun, ketika kami mulai menggunakan /analyze anotasi pada fungsi variadik untuk membuat pemeriksaan tipe berfungsi dengan benar, masalah ini diselesaikan sekali dan untuk semua. Dalam peringatan penganalisis yang berguna, kami menemukan lusinan cacat seperti itu yang dapat menyebabkan crash jika beberapa kondisi yang salah terjadi untuk memulai cabang kode yang sesuai - ini, omong-omong, juga menunjukkan seberapa kecil persentase cakupan kode kami dengan pengujian.

Banyak bug serius yang dilaporkan oleh penganalisis terkait dengan modifikasi kode yang dibuat lama setelah ditulis. Contoh yang sangat umum adalah ketika kode ideal, di mana pointer sebelumnya diperiksa nol sebelum melakukan operasi, kemudian diubah sedemikian rupa sehingga pointer tiba-tiba mulai digunakan tanpa memeriksa. Jika kita mempertimbangkan masalah ini secara terpisah, maka orang dapat mengeluh tentang kompleksitas siklomatik kode yang tinggi, tetapi jika kita melihat sejarah proyek, ternyata alasannya adalah karena pembuat kode tidak dapat menyampaikan premis dengan jelas kepada programmer yang kemudian bertanggung jawab atas refactoring.

Manusia, menurut definisi, tidak dapat memusatkan perhatian mereka pada semuanya sekaligus, jadi fokuslah pada kode yang akan Anda berikan kepada pelanggan terlebih dahulu, dan kurangi perhatian pada kode internal. Port kode secara proaktif dari basis penjualan ke proyek internal. Baru-baru ini, sebuah artikel diterbitkan di mana dikatakan bahwa semua metrik kualitas kode dalam semua keragamannya hampir sama sempurnanya dengan ukuran kode seperti tingkat kesalahan, yang memungkinkan untuk memprediksi jumlah kesalahan dengan akurasi tinggi dari ukuran kode. sendiri. Jadi potong bagian dari kode Anda yang sangat penting dalam hal kualitas.

Jika Anda tidak takut pada inti dari semua kesulitan tambahan yang dibawa oleh pemrograman paralel, Anda sepertinya tidak mempelajari masalah ini dengan benar.

Tidak mungkin untuk melakukan tes benchmark yang andal dalam pengembangan perangkat lunak, tetapi keberhasilan kami dengan analisis kode sangat jelas sehingga saya hanya dapat menyatakan: tidak menggunakan analisis kode tidak bertanggung jawab! Log kerusakan konsol otomatis berisi data objektif yang dengan jelas menunjukkan bahwa Rage, meskipun merupakan pelopor dalam banyak hal, telah terbukti jauh lebih stabil dan lebih sehat daripada kebanyakan game saat ini. Peluncuran Rage di PC sayangnya gagal - Saya berani bertaruh bahwa AMD tidak menggunakan analisis statis saat mengembangkan driver grafis mereka.

Inilah resepnya untuk Anda: jika versi Visual Studio Anda memiliki /analyze bawaan, aktifkan dan coba bekerja seperti ini. Jika saya diminta untuk memilih satu dari banyak alat, saya akan memilih solusi ini dari Microsoft. Untuk semua orang yang bekerja di Visual Studio, saya menyarankan Anda untuk setidaknya mencoba PVS-Studio dalam mode demo. Jika Anda mengembangkan perangkat lunak komersial, membeli alat analisis statis akan menjadi salah satu cara terbaik untuk berinvestasi.

Dan akhirnya, sebuah komentar dari Twitter.

Penyempurnaan aplikasi bisnis pengembang global (CRM, ERP, penagihan, dll.) Dengan mempertimbangkan fitur dan persyaratan khusus dari proses kerja perusahaan dan pengembangan aplikasi bisnis mereka sendiri dari awal adalah standar untuk perusahaan Rusia. Pada saat yang sama, dalam proses penerapan dan pengoperasian aplikasi bisnis, ada ancaman informasi keamanan terkait dengan kesalahan pemrograman (buffer overflow, variabel yang tidak diinisialisasi, dll.) dan adanya fungsi yang melewati mekanisme perlindungan bawaan. Fungsi-fungsi tersebut dibangun pada tahap pengujian dan debugging aplikasi, tetapi karena kurangnya prosedur kontrol keamanan kode, mereka tetap dalam versi produksi aplikasi bisnis. Juga, tidak dapat dijamin bahwa pada tahap pembuatan aplikasi bisnis, pengembang tidak akan dengan sengaja menyematkan kode tambahan yang mengarah pada keberadaan fitur yang tidak dideklarasikan (bookmark perangkat lunak).

Pengalaman menunjukkan bahwa semakin cepat kesalahan atau bookmark ditemukan dalam aplikasi bisnis, semakin sedikit sumber daya yang diperlukan untuk menghilangkannya. Kompleksitas dan biaya tugas mendiagnosis dan menghilangkan kesalahan perangkat lunak atau bookmark pada tahap operasi komersial aplikasi bisnis jauh lebih tinggi daripada parameter serupa dari tugas semacam itu pada tahap penulisan kode sumber.

ELVIS-PLUS menawarkan sistem analisis kode sumber berdasarkan produk pemimpin dunia di bidang ini — HP Fortify Static Code Analyzer (SCA), serta perusahaan Rusia - InfoWatch Appercut dan Inspektur Aplikasi Teknologi Positif.

Tujuan menciptakan Sistem
  • Mengurangi tingkat risiko kerugian finansial langsung dan risiko reputasi akibat serangan terhadap aplikasi bisnis yang mengandung kesalahan atau bookmark.
  • Meningkatkan tingkat keamanan perusahaan sistem Informasi melalui organisasi kontrol, otomatisasi dan sentralisasi manajemen analisis kode sumber aplikasi bisnis.
Tugas diselesaikan oleh Sistem
  • Analisis statistik perangkat lunak untuk bug/kerentanan, dilakukan tanpa menjalankan aplikasi pada tingkat kode sumber.
  • Analisis dinamis perangkat lunak untuk kesalahan/kerentanan, dilakukan setelah perakitan dan peluncuran aplikasi.
  • Implementasi teknologi untuk pengembangan aplikasi bisnis yang aman selama pembuatan dan di seluruh siklus hidup aplikasi dengan menyematkan Sistem dalam lingkungan pengembangan aplikasi.
Arsitektur dan fungsi utama sistem (pada contoh produk HP Fortify SCA)

Analisis Statis, juga dikenal sebagai Pengujian Keamanan Aplikasi Statis (SAST):

  • Mengidentifikasi potensi kerentanan aplikasi secara langsung di tingkat kode.
  • Membantu mengidentifikasi masalah selama proses pengembangan.

Analisis Dinamis, juga dikenal sebagai Pengujian Keamanan Aplikasi Dinamis (DAST):

  • Mendeteksi kerentanan dalam menjalankan aplikasi web dan layanan web dengan mensimulasikan skenario serangan penuh.
  • Memeriksa apakah kerentanan tertentu dapat dieksploitasi dalam praktik.
  • Mempercepat pelaksanaan tindakan korektif, memungkinkan Anda untuk memahami masalah mana yang perlu ditangani terlebih dahulu dan mengapa.

Sistem berdasarkan HP Fortify Software Security Center memungkinkan Anda menerapkan proses otomatis untuk mendeteksi, memprioritaskan, menyelesaikan, melacak, memeriksa, dan mengelola kerentanan dalam perangkat lunak aplikasi bisnis. Alat HP Fortify dapat dibangun ke dalam lingkungan pengembangan terintegrasi (IDE - Lingkungan Pengembangan Terintegrasi), alat kontrol kualitas (QA - Jaminan kualitas) dan sistem pelacakan kesalahan.

Fungsi utama Sistem
  • Implementasi dan otomatisasi proses pendeteksian kerentanan dalam perangkat lunak aplikasi (ASP) pada berbagai tahap pengembangan (pembuatan, debugging, pengujian, operasi, modifikasi).
  • Deteksi kerentanan dalam aplikasi web yang digunakan pada berbagai tahap pengembangan perangkat lunak (pembuatan, debugging, pengujian, operasi, modifikasi).
  • Menyiapkan kondisi dan kriteria untuk mendeteksi kerentanan dalam perangkat lunak aplikasi.
  • Dukungan untuk bahasa pemrograman modern untuk mengidentifikasi ancaman terhadap keamanan perangkat lunak (C/C++, Java, JSP, ASP, .NET, JavaScript, PHP, COBOL, PL/SQL, ABAP, VB6, dll.).
  • Dukungan untuk berbagai alat pengembangan untuk integrasi dengan lingkungan pengembangan aplikasi.
  • Pembentukan laporan tentang masalah keamanan perangkat lunak yang diperiksa dengan peringkat kerentanan yang ditemukan sesuai dengan tingkat risiko.
  • Mengirimkan rekomendasi praktis untuk menghilangkan kerentanan yang terdeteksi dalam kode ke lingkungan pengembangan aplikasi.
  • Memperbarui database kerentanan untuk mengidentifikasi ancaman keamanan perangkat lunak saat ini berdasarkan informasi yang diberikan oleh vendor.
Manfaat menerapkan Sistem
  • Mengurangi biaya pengembangan, pengujian, dan perbaikan kesalahan dalam aplikasi bisnis.
  • Mengurangi biaya pemulihan aplikasi bisnis yang diretas.
  • Meningkatkan efisiensi departemen yang bertanggung jawab untuk memberikan keamanan informasi di perusahaan.

Istilah ini biasanya diterapkan pada analisis yang dilakukan oleh perangkat lunak khusus, sedangkan analisis manual disebut memahami atau pemahaman program.

Bergantung pada alat yang digunakan, kedalaman analisis dapat bervariasi mulai dari menentukan perilaku masing-masing operator hingga analisis yang mencakup semua yang tersedia sumber. Cara menggunakan informasi yang diperoleh selama analisis juga berbeda - dari mengidentifikasi tempat yang mungkin mengandung kesalahan, hingga metode formal yang memungkinkan pembuktian matematis dari setiap properti program (misalnya, kepatuhan perilaku dengan spesifikasi).

Beberapa orang menganggap metrik perangkat lunak dan rekayasa balik sebagai bentuk analisis statis.

Baru-baru ini, analisis statis semakin banyak digunakan dalam verifikasi properti perangkat lunak yang digunakan dalam sistem komputer dengan keandalan tinggi.

Kebanyakan kompiler (seperti GNU C Compiler) menampilkan "peringatan" di layar. peringatan) - pesan bahwa kode tersebut, secara sintaksis benar, kemungkinan besar mengandung kesalahan. Sebagai contoh:

intx; int y = x+ 2 ; // Variabel x tidak diinisialisasi!

Ini adalah analisis statis yang paling sederhana. Kompiler memiliki banyak karakteristik penting lainnya - pertama-tama, kecepatan kerja dan kualitas kode mesin, jadi kompiler memeriksa kode hanya untuk kesalahan yang jelas. Penganalisis statis dirancang untuk analisis kode yang lebih detail.

Jenis Kesalahan yang Dideteksi oleh Penganalisis Statis

  • Perilaku tidak terdefinisi - variabel yang tidak diinisialisasi, akses ke pointer NULL. Kompiler juga menandakan kasus paling sederhana.
  • Pelanggaran diagram blok penggunaan perpustakaan. Misalnya, setiap fopen membutuhkan fclose . Dan jika variabel file hilang sebelum file ditutup, penganalisis mungkin melaporkan kesalahan.
  • Skenario khas yang menghasilkan perilaku tidak terdokumentasi. Pustaka standar C terkenal karena banyak kegagalan teknisnya. Beberapa fungsi, seperti get , pada dasarnya tidak aman. sprintf dan strcpy hanya aman dalam kondisi tertentu.
  • Buffer overflow - ketika program komputer menulis data di luar batas buffer yang dialokasikan dalam memori.

Void doSomething(const char * x) ( char s[ 40 ] ; sprintf (s, "[%s]" , x) ; // sprintf ke buffer lokal, overflow mungkin .... }

  • Skenario khas yang mengganggu lintas platform .

Objek * p = getObject() ; int pNum = reinterpret_cast< int >(p); // true pada x86-32, sebagian pointer akan hilang pada x64; butuh ukuran_t

  • Bug dalam kode berulang. Banyak program mengeksekusi hal yang sama beberapa kali dengan argumen yang berbeda. Biasanya, fragmen yang berulang tidak ditulis dari awal, tetapi diduplikasi dan dikoreksi.

tujuan.x = src.x + dx; tujuan.y = src.y + dx; // Kesalahan, perlu dy!

std::wstring; printf("s adalah %s", s);

  • Parameter yang tidak dapat diubah yang diteruskan ke suatu fungsi adalah tanda persyaratan yang diubah untuk program. Setelah parameter diaktifkan, tetapi sekarang tidak lagi diperlukan. Dalam hal ini, programmer dapat menyingkirkan parameter ini sama sekali - dan logika yang terkait dengannya.

doSomething(int n, bendera bool) // bendera selalu benar( jika (bendera) ( // beberapa logika) kalau tidak ( // kode ada, tapi tidak digunakan) ) melakukanSesuatu(n, benar ); ... doSomething (10, benar); ... doSomething (x.size() , true );

std::string; ...s.kosong(); // kode tidak melakukan apa-apa; Anda mungkin bermaksud s.clear()?

Metode Formal

Alat analisis statis

  • Kerahasiaan
  • lint dan lock_lint disertakan dengan Sun Studio
  • T-SQL Analyzer adalah alat yang dapat melihat modul program dalam database yang menjalankan Microsoft SQL Server 2005 atau 2008 dan mendeteksi potensi masalah yang terkait dengan kualitas kode yang buruk.
  • AK-VS

Lihat juga

  • Semantik formal PL
  • Analisis perangkat lunak
  • Degradasi bertahap
  • SPARK - JAP

Catatan

Tautan


Yayasan Wikimedia. 2010 .

Lihat apa itu "Analisis Kode Statis" di kamus lain:

    - (eng. Analisis program dinamis) analisis perangkat lunak yang dilakukan dengan menjalankan program pada prosesor nyata atau virtual (analisis yang dilakukan tanpa menjalankan program disebut analisis kode statis). Utilitas ... ... Wikipedia

    Analisis aliran kontrol adalah analisis kode statis untuk menentukan urutan eksekusi program. Urutan eksekusi dinyatakan sebagai grafik aliran kontrol. Untuk banyak bahasa, grafik aliran kontrol terlihat jelas di kode sumber ... ... Wikipedia

    Istilah ini memiliki arti lain, lihat BLAST (arti). Pengembang Alat Analisis Statis Tipe BLAST Dirk Beyer, Thomas Henzinger, Ranjit Jhala, Rupak Majumdar, Berkeley Operating sistem Linux, Microsoft Windows… … Wikipedia

    Tabel berikut menyertakan paket perangkat lunak yang merupakan alat pengembangan terintegrasi. Kompiler dan debugger terpisah tidak disebutkan. Mungkin bagian bahasa Inggris memiliki lebih banyak informasi terkini. Isi 1 ActionScript 2 Ada 3 ... Wikipedia

    Debugging adalah tahap pengembangan program komputer di mana kesalahan dideteksi, dilokalisasi dan dihilangkan. Untuk memahami di mana kesalahan terjadi, Anda harus: mencari tahu nilai variabel saat ini; cari tahu jalur mana yang diikuti ... ... Wikipedia

    Ketik Penganalisis kode statis Lab pengembang BiPro Ditulis dalam C++ Sistem operasi Lintas platform Bahasa antarmuka bahasa Inggris ... Wikipedia

Dengan analisis statis, Anda dapat menemukan banyak cacat dan kelemahan berbeda dalam kode sumber bahkan sebelum kode siap dijalankan. Di sisi lain, analisis runtime, atau analisis run-time, terjadi pada perangkat lunak yang sedang berjalan dan mendeteksi masalah saat terjadi, biasanya menggunakan alat yang canggih. Orang mungkin berpendapat bahwa satu bentuk analisis mendahului yang lain, tetapi pengembang dapat menggabungkan kedua metode untuk mempercepat proses pengembangan dan pengujian, serta untuk meningkatkan kualitas produk yang dikirimkan.

Artikel ini pertama-tama membahas metode analisis statis. Ini dapat digunakan untuk mencegah masalah sebelum mereka menembus ke dalam kode utama dan memastikan bahwa kode baru sesuai dengan standar. Menggunakan berbagai teknik analisis, seperti pohon sintaksis abstrak (AST) dan analisis jalur kode, alat analisis statis dapat mengungkap kerentanan tersembunyi, kesalahan logis, cacat implementasi, dan masalah lainnya. Hal ini dapat terjadi baik pada tahap pengembangan di setiap workstation, dan selama perakitan sistem. Artikel ini kemudian mengeksplorasi metode analisis dinamis yang dapat digunakan dalam fase pengembangan modul dan integrasi sistem untuk mengidentifikasi masalah yang terlewatkan oleh analisis statis. Analisis dinamis tidak hanya mendeteksi kesalahan yang terkait dengan pointer dan kesalahan lainnya, tetapi juga memungkinkan untuk mengoptimalkan penggunaan siklus CPU, RAM, memori flash, dan sumber daya lainnya.

Artikel ini juga membahas opsi untuk menggabungkan analisis statis dan dinamis, yang akan membantu mencegah regresi ke tahap pengembangan awal saat produk matang. Pendekatan metode ganda ini membantu menghindari sebagian besar masalah di awal pengembangan, ketika masalah tersebut paling mudah dan paling murah untuk diperbaiki.

Menggabungkan yang terbaik dari kedua dunia

Alat analisis statis menemukan kesalahan perangkat lunak di awal fase pembuatan proyek, biasanya sebelum executable dibuat. Deteksi dini ini sangat berguna untuk proyek sistem tertanam besar di mana pengembang tidak dapat menggunakan alat analisis dinamis sampai perangkat lunak cukup lengkap untuk dijalankan pada sistem target.

Pada tahap analisis statis, area kode sumber dengan titik lemah ditemukan dan dijelaskan, termasuk kerentanan tersembunyi, kesalahan logis, cacat implementasi, kesalahan dalam operasi paralel, kondisi batas yang jarang terjadi, dan banyak masalah lainnya. Misalnya, alat analisis statis Klocwork Insight melakukan analisis mendalam dari kode sumber di tingkat sintaksis dan semantik. Alat-alat ini juga melakukan analisis antar-prosedural yang canggih dari kontrol dan aliran data dan menggunakan teknik decoying tingkat lanjut, mengevaluasi nilai-nilai yang akan diambil variabel, dan memodelkan perilaku potensial program saat runtime.

Pengembang dapat menggunakan alat analisis statis kapan saja selama fase pengembangan, bahkan ketika hanya sebagian kecil dari proyek yang telah ditulis. Namun, semakin lengkap kodenya, semakin baik. Dengan analisis statis, semua jalur eksekusi kode potensial dapat dilihat - ini jarang terjadi dalam pengujian normal, kecuali jika proyek memerlukan cakupan kode 100%. Misalnya, analisis statis dapat mendeteksi kesalahan pemrograman yang terkait dengan kondisi tepi atau kesalahan jalur yang tidak diuji pada waktu desain.

Karena analisis statis mencoba memprediksi perilaku program berdasarkan model kode sumber, kadang-kadang ditemukan "bug" yang sebenarnya tidak ada - inilah yang disebut "positif palsu" (positif palsu). Banyak alat analisis statis modern menerapkan teknik yang ditingkatkan untuk menghindari masalah ini dan melakukan analisis yang sangat akurat.

Analisis statis: argumen "untuk" Analisis Statis: Argumen Melawan
Digunakan di awal siklus hidup perangkat lunak, sebelum kode siap dijalankan dan sebelum pengujian dimulai.

Basis kode yang ada yang telah diuji dapat dianalisis.

Alat dapat diintegrasikan ke dalam lingkungan pengembangan sebagai bagian dari komponen yang digunakan dalam "pembuatan malam" dan sebagai bagian dari perangkat meja kerja pengembang.

Biaya rendah: tidak perlu membuat program pengujian atau stub; pengembang dapat menjalankan analisis mereka sendiri.

Bug dan kerentanan perangkat lunak dapat ditemukan yang tidak selalu mengarah pada kegagalan program atau memengaruhi perilaku program selama eksekusi sebenarnya.

Probabilitas bukan nol dari "positif palsu".

Tabel 1- Argumen "untuk" dan "melawan" analisis statis.

Alat analisis dinamis mendeteksi kesalahan pemrograman dalam kode yang sedang dieksekusi. Pada saat yang sama, pengembang memiliki kesempatan untuk mengamati atau mendiagnosis perilaku aplikasi selama eksekusi, dalam kasus yang ideal, langsung di lingkungan target.

Dalam banyak kasus, alat analisis dinamis memodifikasi kode aplikasi sumber atau biner untuk memasang perangkap, atau kait, untuk pengukuran instrumental. Kait ini dapat digunakan untuk mendeteksi kesalahan program saat dijalankan, menganalisis penggunaan memori, cakupan kode, dan memeriksa kondisi lainnya. Alat analisis dinamis dapat menghasilkan informasi akurat tentang status tumpukan, yang memungkinkan debugger menemukan penyebab kesalahan. Oleh karena itu, ketika alat analisis dinamis menemukan bug, kemungkinan besar bug nyata yang dapat diidentifikasi dan diperbaiki oleh programmer dengan cepat. Perlu dicatat bahwa untuk menciptakan situasi kesalahan pada saat dijalankan, harus ada kondisi yang diperlukan di mana kesalahan program terjadi. Oleh karena itu, pengembang harus membuat semacam kasus uji untuk mengimplementasikan skenario tertentu.

Analisis dinamis: argumen "untuk" Analisis Dinamis: Argumen Melawan
Jarang terjadi "positif palsu" - produktivitas tinggi dalam menemukan kesalahan

Tumpukan penuh dan jejak runtime dapat diproduksi untuk melacak penyebab kesalahan.

Kesalahan ditangkap dalam konteks sistem yang sedang berjalan, baik di dunia nyata maupun dalam mode simulasi.

Ada intervensi dalam perilaku sistem secara real time; tingkat intervensi tergantung pada jumlah sisipan alat yang digunakan. Ini tidak selalu menyebabkan masalah, tetapi ini adalah sesuatu yang perlu diingat ketika bekerja dengan kode waktu kritis.

Kelengkapan analisis kesalahan tergantung pada tingkat cakupan kode. Dengan demikian, jalur kode yang berisi kesalahan harus dilalui, dan dalam kasus uji, kondisi yang diperlukan harus dibuat untuk menciptakan situasi kesalahan.

Meja 2- Argumen "untuk" dan "melawan" analisis dinamis.

Deteksi kesalahan dini untuk mengurangi biaya pengembangan

Semakin cepat kesalahan perangkat lunak terdeteksi, semakin cepat dan murah dapat diperbaiki. Oleh karena itu, alat analisis statis dan dinamis memiliki nilai nyata dalam menemukan bug di awal siklus hidup perangkat lunak. Berbagai studi produk industri menunjukkan bahwa memperbaiki masalah pada tahap pengujian sistem (untuk mengkonfirmasi kualitas pekerjaannya, QA) atau setelah pengiriman sistem ternyata beberapa kali lipat lebih mahal daripada memperbaiki masalah yang sama di tahap pengembangan perangkat lunak. Banyak organisasi memiliki perkiraan mereka sendiri untuk biaya perbaikan cacat. pada gambar. Gambar 1 memberikan data tentang masalah yang sedang dibahas, diambil dari buku yang sering dikutip oleh Capers Jones. "Pengukuran Perangkat Lunak Terapan".

Beras. satu- Seiring berjalannya proyek, biaya perbaikan cacat perangkat lunak dapat meningkat secara eksponensial. Alat analisis statis dan dinamis membantu mencegah biaya ini dengan mendeteksi bug di awal siklus hidup perangkat lunak.

Analisis Statis

Analisis statis telah ada dalam praktik pengembangan perangkat lunak hampir selama pengembangan perangkat lunak itu sendiri telah ada. Dalam bentuk aslinya, analisis direduksi menjadi pemantauan kepatuhan terhadap standar gaya pemrograman (lint). Pengembang menggunakannya langsung di tempat kerja mereka. Ketika datang untuk mendeteksi bug, alat analisis statis awal berfokus pada apa yang ada di permukaan: gaya pemrograman dan kesalahan sintaksis umum. Misalnya, bahkan alat analisis statis yang paling sederhana pun dapat mendeteksi kesalahan seperti ini:

int foo(int x, int* ptr) ( if(x & 1); ( *ptr = x; kembali; ) ... )

Di sini, penggunaan titik koma tambahan yang salah mengarah ke hasil yang berpotensi membawa bencana: penunjuk parameter input fungsi didefinisikan ulang dalam kondisi yang tidak terduga. Pointer selalu didefinisikan ulang, terlepas dari kondisi yang diperiksa.

Alat analisis awal berfokus terutama pada kesalahan sintaksis. Jadi sementara bug serius dapat ditemukan, sebagian besar masalah yang ditemukan relatif sepele. Selain itu, konteks kode yang cukup kecil disediakan untuk alat sehingga hasil yang akurat dapat diharapkan. Ini karena pekerjaan dilakukan selama siklus kompilasi/tautan pengembangan yang khas, dan apa yang dilakukan pengembang hanyalah sepotong kecil kode dalam kumpulan besar sistem perangkat lunak. Kekurangan seperti itu mengarah pada fakta bahwa alat analisis didasarkan pada perkiraan dan hipotesis tentang apa yang mungkin terjadi di luar "kotak pasir" pengembang. Dan ini, pada gilirannya, menghasilkan peningkatan volume laporan dengan "positif palsu".

Generasi berikutnya dari alat analisis statis mencatat kekurangan ini dan memperluas jangkauannya di luar analisis sintaksis dan semantik. Dalam alat baru, representasi atau model yang diperluas dari kode yang dihasilkan dibangun (sesuatu yang mirip dengan fase kompilasi), dan kemudian semua cara yang mungkin untuk mengeksekusi kode dimodelkan sesuai dengan model. Selanjutnya, alur logis dipetakan ke jalur ini dengan kontrol simultan tentang bagaimana dan di mana objek data dibuat, digunakan, dan dihancurkan. Dalam proses menganalisis modul program, prosedur untuk menganalisis kontrol antarprosedural dan aliran data dapat dihubungkan. Ini juga meminimalkan "positif palsu" dengan menggunakan pendekatan baru untuk memotong jalur yang salah, mengevaluasi nilai yang dapat diambil oleh variabel, dan memodelkan perilaku potensial saat berjalan secara real time. Untuk menghasilkan data tingkat ini dalam alat analisis statis, perlu untuk menganalisis seluruh basis kode proyek, melakukan tata letak sistem integral, dan tidak hanya bekerja dengan hasil yang diperoleh di "kotak pasir" di desktop pengembang.

Untuk melakukan bentuk analisis yang canggih ini, alat analisis statis menangani dua jenis pemeriksaan kode utama:

  • Pemeriksaan pohon sintaksis abstrak- untuk memeriksa sintaks dasar dan struktur kode.
  • Analisis jalur kode- untuk melakukan analisis yang lebih lengkap, yang bergantung pada pemahaman status objek data program pada titik tertentu di jalur eksekusi kode.

Pohon sintaksis abstrak

Pohon sintaksis abstrak hanyalah representasi struktur pohon dari kode sumber, seperti yang mungkin dihasilkan dalam langkah-langkah pra-kompiler. Pohon berisi dekomposisi satu-ke-satu rinci dari struktur kode, memungkinkan alat untuk melakukan pencarian sederhana untuk titik sintaks anomali.

Sangat mudah untuk membuat pemeriksa yang memeriksa standar mengenai konvensi penamaan dan pembatasan panggilan fungsi, seperti memeriksa perpustakaan yang tidak aman. Tujuan melakukan pemeriksaan AST biasanya untuk menarik semacam inferensi dari kode itu sendiri tanpa menggunakan pengetahuan tentang bagaimana kode berperilaku selama eksekusi.

Banyak alat menawarkan pemeriksaan berbasis AST untuk berbagai bahasa, termasuk alat sumber terbuka seperti PMD untuk Java. Beberapa alat menggunakan tata bahasa jalur-X atau tata bahasa turunan jalur-X untuk menentukan kondisi yang menarik untuk mengontrol program. Alat lain menyediakan mekanisme canggih untuk memungkinkan pengguna membuat sendiri program sendiri pemeriksaan berbasis AST. Jenis tinjauan ini relatif mudah dilakukan, dan banyak organisasi membuat program tinjauan baru jenis ini untuk memverifikasi kepatuhan terhadap standar pengkodean perusahaan atau praktik terbaik yang direkomendasikan industri.

Analisis jalur kode

Mari kita lihat contoh yang lebih kompleks. Sekarang, daripada mencari kasus pelanggaran gaya pemrograman, kami ingin memeriksa apakah dereferensi pointer yang dicoba akan bekerja dengan benar atau gagal:

Jika(x & 1) ptr = NULL; *ptr = 1;

Pemeriksaan yang dangkal dari fragmen mengarah pada kesimpulan yang jelas bahwa variabel ptr dapat menjadi NULL jika variabel x ganjil, dan kondisi ini, ketika direferensikan, pasti akan mengarah ke halaman nol. Namun, saat membuat program uji berdasarkan AST, menemukan kesalahan program seperti itu sangat bermasalah. Pertimbangkan pohon AST (disederhanakan untuk kejelasan) yang akan dihasilkan untuk cuplikan kode di atas:

Blok Pernyataan Jika-pernyataan Check-Expression Binary-operator & x 1 True-Branch Expression-statement Assignment-operator = ptr 0 Expression-statement Assignment-operator = Dereference-pointer - ptr 1 Dalam kasus seperti itu, tidak ada pencarian pohon atau daftar sederhana dari node gagal mendeteksi, dalam bentuk yang cukup umum, upaya yang dilakukan (setidaknya terkadang tidak valid) untuk melakukan dereferensi penunjuk ptr. Dengan demikian, alat parsing tidak bisa hanya mencari model sintaks. Penting juga untuk menganalisis siklus hidup objek data saat muncul dan digunakan dalam logika kontrol selama eksekusi.

Analisis jalur kode melacak objek dalam jalur eksekusi sehingga validator dapat menentukan apakah data digunakan secara akurat dan benar. Penggunaan analisis jalur kode memperluas jangkauan pertanyaan yang dapat dijawab selama analisis statis. Alih-alih hanya menganalisis kebenaran kode program, analisis jalur kode mencoba menentukan "niat" kode dan memeriksa apakah kode ditulis sesuai dengan maksud tersebut. Ini dapat memberikan jawaban atas pertanyaan-pertanyaan berikut:

  • Apakah objek yang baru dibuat dibebaskan sebelum semua referensi dihapus dari ruang lingkup?
  • Apakah rentang nilai yang diizinkan telah diperiksa untuk beberapa objek data sebelum objek diteruskan ke fungsi OS?
  • Apakah string karakter diperiksa untuk karakter khusus sebelum meneruskan string sebagai kueri SQL?
  • Akankah operasi penyalinan menyebabkan buffer overflow?
  • Apakah aman untuk memanggil fungsi ini saat ini?

Dengan menganalisis jalur eksekusi kode dengan cara ini, baik maju dari pengaktifan peristiwa ke skrip target dan kembali dari pengaktifan peristiwa ke inisialisasi data yang diperlukan, alat akan dapat menjawab pertanyaan dan mengeluarkan laporan kesalahan jika skrip target atau inisialisasi dijalankan atau tidak dilaksanakan seperti yang diharapkan.

Implementasi kemungkinan seperti itu sangat penting untuk melakukan analisis lanjutan dari kode sumber. Oleh karena itu, pengembang harus mencari alat yang menggunakan analisis jalur kode lanjutan untuk mendeteksi kebocoran memori, dereferensi penunjuk yang buruk, transfer data yang tidak aman atau tidak valid, pelanggaran konkurensi, dan banyak kondisi bermasalah lainnya.

Urutan tindakan saat melakukan analisis statis

Analisis statis dapat mendeteksi masalah pada dua titik kunci dalam proses pengembangan: selama penulisan program di tempat kerja dan pada tahap menghubungkan sistem. Seperti yang telah disebutkan, generasi alat saat ini bekerja terutama pada tahap penautan sistem, ketika memungkinkan untuk menganalisis aliran kode seluruh sistem, yang mengarah pada hasil diagnostik yang sangat akurat.

Unik dalam jenisnya, Klocwork Insight memungkinkan Anda untuk menganalisis kode yang dibuat di tempat kerja pengembang tertentu, sambil menghindari masalah yang terkait dengan diagnostik yang tidak akurat, yang biasanya merupakan karakteristik alat semacam ini. Klocwork menyediakan Analisis Desktop Terhubung, yang menganalisis kode pengembang dengan pemahaman tentang semua dependensi sistem. Ini menghasilkan analisis lokal yang sama akurat dan kuatnya dengan analisis sistem terpusat, tetapi semuanya sebelum kode dirakit sepenuhnya.

Dari perspektif pengurutan analisis, kemampuan ini memungkinkan pengembang untuk melakukan analisis statis yang akurat dan berkualitas tinggi di awal siklus hidup pengembangan. Masalah alat Klockwork Insight ke Lingkungan Pengembang Terpadu (IDE) atau garis komando pesan tentang semua masalah saat pengembang menulis kode dan secara berkala melakukan operasi kompilasi / penautan. Penerbitan pesan dan laporan tersebut terjadi sebelum analisis dinamis dilakukan dan sebelum semua pengembang menyatukan kode mereka.

Beras. 2- Urutan eksekusi analisis statis.

Teknologi Analisis Dinamis

Untuk mendeteksi kesalahan pemrograman dalam alat analisis dinamis, fragmen kecil kode sering dimasukkan baik secara langsung ke dalam kode sumber program (injeksi ke dalam kode sumber) atau ke dalam kode yang dapat dieksekusi (injeksi ke kode objek). Dalam segmen kode seperti itu, "pemeriksaan sanitasi" status program dilakukan dan laporan kesalahan dikeluarkan jika ditemukan sesuatu yang tidak benar atau tidak dapat dioperasikan. Fungsi lain mungkin terlibat dalam alat tersebut, seperti melacak alokasi memori dan penggunaan dari waktu ke waktu.

Teknologi analisis dinamis meliputi:

  • Penempatan sisipan dalam kode sumber pada tahap preprocessing– sebuah fragmen kode khusus dimasukkan ke dalam kode sumber aplikasi sebelum kompilasi untuk mendeteksi kesalahan. Pendekatan ini tidak memerlukan pengetahuan rinci tentang lingkungan runtime, dan sebagai hasilnya, metode ini populer di antara alat pengujian dan analisis sistem tertanam. Contoh alat tersebut adalah produk IBM Rational Test RealTime.
  • Menempatkan Sisipan dalam Kode Objek- Untuk alat analisis dinamis seperti itu, Anda harus memiliki pengetahuan yang cukup tentang lingkungan runtime untuk dapat menyisipkan kode secara langsung ke file dan pustaka yang dapat dieksekusi. Dengan pendekatan ini, Anda tidak perlu mengakses kode sumber program atau menautkan ulang aplikasi. Contoh alat tersebut adalah IBM Rational Purify.
  • Memasukkan kode pada waktu kompilasi- pengembang menggunakan kunci khusus (opsi) kompiler untuk disematkan ke dalam kode sumber. Kemampuan kompiler untuk mendeteksi kesalahan digunakan. Sebagai contoh, compiler GNU C/C++ 4.x menggunakan teknologi Mudflap untuk mendeteksi masalah dengan operasi pointer.
  • Pustaka Runtime Khusus– untuk mendeteksi kesalahan dalam parameter yang diteruskan, pengembang menggunakan versi debug dari pustaka sistem. Fungsi seperti strcpy() terkenal karena kemungkinan pointer null atau salah saat runtime. Saat menggunakan versi debug perpustakaan, parameter "buruk" seperti itu terdeteksi. Teknologi ini tidak memerlukan penautan ulang aplikasi dan mempengaruhi kinerja pada tingkat yang lebih rendah daripada penggunaan penuh sisipan dalam kode sumber/objek. Teknologi ini digunakan dalam alat analisis RAM di QNX® Momentics® IDE.

Dalam artikel ini, kita akan melihat teknologi yang digunakan dalam alat pengembang QNX Momentics, dengan fokus khusus pada Mudflap GCC dan pustaka runtime khusus.

GNU C/C++ Mudflap: injeksi waktu kompilasi ke dalam kode sumber

Alat Mudflap, hadir dalam versi 4.x dari GNU C/C++ Compiler (GCC), menggunakan injeksi waktu kompilasi ke dalam kode sumber. Pada saat yang sama, selama eksekusi, struktur diperiksa yang berpotensi membawa kemungkinan kesalahan. Fokus dari Mudflap adalah pada operasi pointer, karena mereka adalah sumber dari banyak kesalahan run-time untuk program yang ditulis dalam C dan C++.

Dengan dimasukkannya Mudflap, kompiler GCC memiliki pass lain ketika memasukkan kode verifikasi untuk operasi pointer. Kode yang ditempelkan biasanya melakukan pemeriksaan validasi pada nilai pointer yang diteruskan. Nilai penunjuk yang salah akan menyebabkan GCC mengeluarkan pesan ke perangkat keluaran kesalahan standar konsol (stderr). Pemeriksa pointer Mudflap tidak hanya memeriksa pointer untuk null: databasenya menyimpan alamat memori untuk objek aktual dan properti objek, seperti lokasi dalam kode sumber, cap tanggal/waktu, stack backtrace ketika memori dialokasikan dan tidak dialokasikan. Basis data semacam itu memungkinkan Anda untuk dengan cepat mendapatkan data yang diperlukan saat menganalisis operasi akses memori dalam kode sumber program.

Fungsi perpustakaan seperti strcpy() tidak memeriksa parameter yang diteruskan. Fungsi seperti itu juga tidak diuji oleh Mudflap. Namun, di Mudflap dimungkinkan untuk membuat pembungkus simbol untuk pustaka yang ditautkan secara statis atau sisipan untuk pustaka dinamis. Dengan teknologi ini, lapisan tambahan dibuat antara aplikasi dan perpustakaan, yang memungkinkan untuk memeriksa validitas parameter dan mengeluarkan pesan tentang terjadinya penyimpangan. Mudflap menggunakan algoritma heuristik berdasarkan pengetahuan tentang batas memori yang digunakan oleh aplikasi (heap, stack, kode dan segmen data, dan sebagainya) untuk menentukan apakah nilai pointer yang dikembalikan valid.

Menggunakan opsi baris perintah kompiler GCC, pengembang dapat mengaktifkan fitur Mudflap untuk menyisipkan fragmen kode dan mengontrol perilaku, seperti mengelola pelanggaran (batas, nilai), melakukan pemeriksaan dan pengaturan tambahan, mengaktifkan heuristik dan diagnostik mandiri. Misalnya, sakelar -fmudflap mengatur konfigurasi Mudflap default. Pesan kompiler tentang pelanggaran yang ditemukan oleh Mudflap dicetak ke konsol keluaran (stderr) atau ke baris perintah. Output verbose memberikan informasi tentang pelanggaran dan variabel dan fungsi yang terlibat, serta lokasi kode. Informasi ini dapat secara otomatis diimpor ke IDE, di mana informasi tersebut dirender dan dilacak tumpukannya. Dengan menggunakan data ini, pengembang dapat dengan cepat menavigasi ke tempat yang sesuai dalam kode sumber program.

pada gambar. Gambar 3 menunjukkan contoh bagaimana kesalahan disajikan dalam IDE, bersama dengan informasi penelusuran balik yang sesuai. Backtrace berfungsi sebagai tautan ke kode sumber, memungkinkan pengembang untuk dengan cepat mendiagnosis penyebab masalah.

Menggunakan Mudflap dapat meningkatkan waktu tautan dan dapat menurunkan kinerja saat dijalankan. Data yang disajikan dalam artikel “Mudflap: Pemeriksaan Penggunaan Pointer untuk C/C++” menunjukkan bahwa dengan mengaktifkan Mudflap, waktu tautan meningkat 3…5 kali, dan program mulai berjalan 1,25 hingga 5 kali lebih lambat. aplikasi waktu-kritis harus menggunakan fitur ini dengan hati-hati.Namun, Mudflap adalah alat yang ampuh untuk mengidentifikasi konstruksi kode yang rawan kesalahan dan berpotensi fatal.QNX berencana untuk menggunakan alat Mudflap di versi mendatang dari alat analisis dinamis mereka.

Beras. 3- Menggunakan informasi penelusuran balik yang ditampilkan di QNX Momentics IDE untuk menemukan kode sumber yang menyebabkan kesalahan.

Versi debug perpustakaan runtime

Seiring dengan penggunaan sisipan debug khusus di pustaka runtime, yang menyebabkan tambahan memori dan biaya waktu yang signifikan pada tahap tautan dan runtime, pengembang dapat menggunakan pustaka runtime yang telah diinstrumentasi sebelumnya. Di perpustakaan semacam itu, beberapa kode ditambahkan di sekitar pemanggilan fungsi, yang tujuannya adalah untuk memeriksa validitas parameter input. Misalnya, pertimbangkan seorang teman lama, fungsi penyalinan string:

strcpy(a,b);

Dibutuhkan dua parameter, keduanya merupakan pointer ke tipe arang: satu untuk string asli ( b) dan satu lagi untuk string hasil ( sebuah). Terlepas dari kesederhanaan ini, fungsi ini dapat menjadi sumber dari banyak kesalahan:

  • jika nilai penunjuk sebuah nol atau tidak valid, maka menyalin ke tujuan tersebut akan mengakibatkan kesalahan akses memori ditolak;
  • jika nilai penunjuk b nol atau tidak valid, maka membaca informasi dari alamat ini akan mengakibatkan kesalahan akses memori ditolak;
  • jika di akhir baris b jika karakter pengakhiran "0" tidak ada, lebih banyak karakter dari yang diharapkan akan disalin ke string tujuan;
  • jika ukuran tali b lebih dari memori yang dialokasikan untuk string sebuah, maka lebih banyak byte dari yang diharapkan akan ditulis ke alamat yang ditentukan (skenario buffer overflow yang khas).

Versi debug perpustakaan memeriksa nilai parameter ' sebuah' dan ' b'. Panjang string juga diperiksa untuk memastikan mereka kompatibel. Jika parameter yang tidak valid ditemukan, pesan alarm yang sesuai akan dikeluarkan. Di lingkungan QNX Momentics, pesan kesalahan ini diimpor dari sistem target dan ditampilkan di layar. Lingkungan QNX Momentics juga menggunakan alokasi memori dan teknologi pelacakan dealokasi untuk memungkinkan analisis mendalam penggunaan RAM.

Versi debug perpustakaan akan bekerja dengan aplikasi apa pun yang menggunakan fungsinya; tidak perlu memasukkan apapun perubahan tambahan ke dalam kode. Selain itu, pengembang dapat menambahkan perpustakaan selama startup aplikasi. Pustaka kemudian akan mengganti bagian yang sesuai dari pustaka standar lengkap, menghilangkan kebutuhan untuk menggunakan versi debug dari pustaka lengkap. Di QNX Momentics IDE, pengembang dapat menambahkan pustaka semacam itu saat program dimulai sebagai bagian dari sesi debug interaktif normal. pada gambar. Gambar 4 menunjukkan contoh bagaimana QNX Momentics mendeteksi dan melaporkan kesalahan memori.

Versi debug pustaka menyediakan metode "non-agresif" yang telah terbukti untuk mendeteksi kesalahan saat memanggil fungsi pustaka. Teknik ini ideal untuk analisis RAM dan metode analisis lain yang bergantung pada pasangan panggilan yang cocok, seperti malloc() dan free(). Dengan kata lain, teknologi ini hanya dapat mendeteksi kesalahan run-time untuk kode dengan panggilan perpustakaan. Itu tidak mendeteksi banyak kesalahan tipikal, seperti dereferensi penunjuk sebaris atau aritmatika penunjuk yang salah. Biasanya, saat debugging, hanya sebagian dari panggilan sistem yang dipantau. Anda dapat mempelajari lebih lanjut tentang ini di artikel.

Beras. empat- Analisis RAM dilakukan dengan menempatkan jebakan di area panggilan API yang terkait dengan akses memori.

Urutan tindakan dalam analisis dinamis

Singkatnya, analisis dinamis melibatkan penangkapan peristiwa pelanggaran atau peristiwa penting lainnya dalam sistem target yang disematkan, mengimpor informasi ini ke dalam lingkungan pengembangan, dan kemudian menggunakan alat visualisasi untuk mengidentifikasi bagian kode yang bermasalah dengan cepat.

Seperti yang ditunjukkan pada gambar. 5, analisis dinamis tidak hanya memungkinkan Anda untuk mendeteksi kesalahan, tetapi juga membantu menarik perhatian pengembang ke detail konsumsi memori, siklus CPU, ruang disk, dan sumber daya lainnya. Proses analisis terdiri dari beberapa langkah, dan alat analisis dinamis yang baik memberikan dukungan kuat untuk setiap langkah:

  1. Pengamatan- Pertama-tama, ia menangkap kesalahan runtime, mendeteksi kebocoran memori dan menampilkan semua hasil di IDE.
  2. Pengaturan- kemudian pengembang memiliki kesempatan untuk melacak setiap kesalahan kembali ke baris sumber yang menyinggung. Dengan integrasi yang baik ke dalam IDE, setiap kesalahan akan ditampilkan di layar. Pengembang hanya perlu mengklik baris kesalahan, dan fragmen kode sumber terbuka dengan baris yang memutus pekerjaan. Dalam banyak kasus, pengembang dapat dengan cepat memperbaiki masalah menggunakan pelacakan tumpukan yang tersedia dan alat kode sumber tambahan di IDE (penampil panggilan fungsi, pelacak panggilan, dll.).
  3. membuat profil– Dengan memperbaiki bug yang terdeteksi dan kebocoran memori, pengembang dapat menganalisis penggunaan sumber daya dari waktu ke waktu, termasuk puncak, rata-rata beban, dan kelebihan sumber daya. Idealnya, alat analisis akan memberikan representasi visual dari penggunaan sumber daya jangka panjang, yang memungkinkan Anda untuk segera mengidentifikasi lonjakan alokasi memori dan anomali lainnya.
  4. Pengoptimalan– menggunakan informasi dari tahap pembuatan profil, pengembang sekarang dapat melakukan analisis "baik" dari penggunaan sumber daya program. Antara lain, pengoptimalan tersebut dapat meminimalkan puncak sumber daya dan penggunaan berlebihan, termasuk penggunaan RAM dan CPU.

Beras. 5- Urutan tindakan khas untuk analisis dinamis

Menggabungkan urutan tindakan dari berbagai jenis analisis di lingkungan pengembangan

Masing-masing alat analisis statis dan dinamis memiliki kekuatannya sendiri. Oleh karena itu, tim pengembangan harus menggunakan alat ini bersama-sama. Misalnya, alat analisis statis mampu mendeteksi kesalahan yang terlewatkan oleh alat analisis dinamis, karena alat analisis dinamis hanya menangkap kesalahan jika potongan kode yang salah dieksekusi selama pengujian. Di sisi lain, alat analisis dinamis mendeteksi kesalahan perangkat lunak dalam proses akhir yang berjalan. Hampir tidak perlu berdiskusi tentang kesalahan jika penggunaan pointer nol telah ditemukan.

Idealnya, seorang pengembang akan menggunakan kedua alat analisis dalam pekerjaan sehari-hari mereka. Tugas ini sangat difasilitasi jika alat-alat tersebut terintegrasi dengan baik ke dalam lingkungan pengembangan di tempat kerja.

Berikut adalah contoh penggunaan bersama dari dua jenis alat:

  1. Di awal hari kerja, pengembang melihat laporan hasil pembangunan malam. Laporan ini mencakup kesalahan build itu sendiri dan hasil analisis statis yang dilakukan selama build.
  2. Laporan analisis statis mencantumkan cacat yang terdeteksi bersama dengan informasi yang akan membantu Anda memperbaikinya, termasuk tautan ke kode sumber. Dengan menggunakan IDE, pengembang dapat menandai setiap situasi sebagai bug yang benar atau "positif palsu". Setelah itu, kesalahan aktual yang ada diperbaiki.
  3. Pengembang menyimpan perubahan yang dibuat secara lokal, di dalam IDE, bersama dengan cuplikan kode baru. Pengembang tidak melakukan perubahan ini kembali ke sistem kontrol sumber sampai perubahan telah ditinjau dan diuji.
  4. Pengembang menganalisis dan memperbaiki kode baru menggunakan alat analisis statis di tempat kerja lokal. Untuk memastikan deteksi kesalahan berkualitas tinggi dan tidak adanya "positif palsu", analisis menggunakan informasi yang diperluas di tingkat sistem. Informasi ini diambil dari proses pembuatan/analisis malam.
  5. Setelah menganalisis dan "membersihkan" kode baru apa pun, pengembang membuat kode tersebut menjadi gambar uji lokal atau yang dapat dieksekusi.
  6. Menggunakan alat analisis dinamis, pengembang menjalankan tes untuk memverifikasi perubahan yang dibuat.
  7. Dengan bantuan IDE, pengembang dapat dengan cepat mengidentifikasi dan memperbaiki bug yang dilaporkan melalui alat analisis dinamis. Kode dianggap final dan siap digunakan jika telah melalui analisis statis, pengujian unit, dan analisis dinamis.
  8. Pengembang mengirimkan perubahan ke sistem kontrol sumber; setelah itu, kode yang dimodifikasi berpartisipasi dalam proses penautan malam berikutnya.

Alur kerja ini mirip dengan proyek menengah hingga besar yang sudah menggunakan build malam, kontrol kode sumber, dan kepemilikan kode. Karena alat terintegrasi ke dalam IDE, pengembang dapat dengan cepat melakukan analisis statis dan dinamis tanpa menyimpang dari alur kerja biasa. Akibatnya, kualitas kode meningkat secara signifikan pada tahap pembuatan kode sumber.

Peran arsitektur RTOS

Dalam kerangka diskusi tentang alat analisis statis dan dinamis, penyebutan arsitektur RTOS mungkin tampak tidak tepat. Tetapi ternyata RTOS yang dibangun dengan baik dapat sangat memudahkan pendeteksian, pelokalan, dan penyelesaian banyak bug perangkat lunak.

Misalnya, dalam RTOS mikrokernel seperti QNX Neutrino, semua aplikasi, driver perangkat, sistem file, dan tumpukan jaringan berada di luar kernel di ruang alamat yang terpisah. Akibatnya, semuanya terisolasi dari nukleus dan satu sama lain. Pendekatan ini memberikan tingkat lokalisasi kegagalan tertinggi: kegagalan salah satu komponen tidak menyebabkan runtuhnya sistem secara keseluruhan. Selain itu, ternyata mudah untuk mengisolasi kesalahan terkait RAM atau kesalahan logis lainnya ke komponen yang tepat yang menyebabkan kesalahan ini.

Misalnya, jika driver perangkat mencoba mengakses memori di luar wadah prosesnya, maka OS dapat mengidentifikasi proses, menunjukkan lokasi kesalahan, dan menghasilkan file dump yang dapat dilihat oleh debugger kode sumber. Pada saat yang sama, sisa sistem akan terus bekerja, dan pengembang dapat melokalisasi masalah dan berupaya memperbaikinya.

Beras. 6- Pada OS mikrokernel, kegagalan dalam RAM untuk driver, tumpukan protokol, dan layanan lain tidak akan menyebabkan proses lain atau kernel mogok. Selain itu, OS dapat langsung mendeteksi upaya tidak sah untuk mengakses memori dan menunjukkan dari kode mana upaya ini dilakukan.

Dibandingkan dengan kernel OS konvensional, mikrokernel memiliki Mean Time to Repair (MTTR) yang sangat singkat setelah kegagalan. Pertimbangkan apa yang terjadi ketika driver perangkat mogok: OS dapat mematikan driver, memulihkan sumber daya yang digunakan oleh driver, dan memulai ulang driver. Ini biasanya memakan waktu beberapa milidetik. Dalam sistem operasi monolitik yang khas, perangkat harus di-boot ulang - proses ini dapat berlangsung dari beberapa detik hingga beberapa menit.

Catatan akhir

Alat analisis statis dapat mendeteksi kesalahan pemrograman bahkan sebelum kode dieksekusi. Bahkan ditemukan kesalahan-kesalahan yang tidak terdeteksi pada tahap pengujian blok, pengujian sistem, dan juga pada tahap integrasi, karena sangat sulit untuk menyediakan cakupan kode penuh untuk aplikasi yang kompleks, dan ini membutuhkan biaya yang signifikan. Selain itu, tim pengembangan dapat menggunakan alat analisis statis selama pembuatan sistem reguler untuk memastikan bahwa setiap bagian dari kode baru dianalisis.

Sementara itu, alat analisis dinamis mendukung fase integrasi dan pengujian dengan melaporkan kesalahan (atau potensi masalah) yang terjadi selama eksekusi program ke lingkungan pengembangan. Alat-alat ini juga menyediakan penelusuran lengkap kembali ke tempat kesalahan terjadi. Dengan menggunakan informasi ini, pengembang dapat melakukan debugging post-mortem dari kegagalan program misterius atau sistem crash dalam waktu yang jauh lebih singkat. Analisis dinamis melalui pelacakan tumpukan dan variabel dapat mengungkapkan penyebab yang mendasari masalah - ini lebih baik daripada menggunakan pernyataan “if (ptr != NULL)” di semua tempat untuk mencegah dan mengatasi crash.

Penggunaan deteksi dini, cakupan pengujian kode yang lebih baik dan lengkap, bersama dengan koreksi kesalahan, membantu pengembang untuk membuat perangkat lunak berkualitas lebih baik dalam waktu yang lebih singkat.

Bibliografi

  • Eigler, Frank Ch., “Mudflap: Pemeriksaan Penggunaan Pointer untuk C/C++”, Prosiding GCC Developers Summit 2003, hal. 57-70. http://www.linux.org.uk/~ajh/gcc/gccsummit-2003-proceedings.pdf
  • “Analisis Heap: Menjadikan Kesalahan Memori sebagai Masa Lalu”, Panduan Programmer QNX Neutrino RTOS. http://pegasus.ott.qnx.com/download/download/16853/neutrino_prog.pdf

Tentang Sistem Perangkat Lunak QNX

QNX Software Systems adalah anak perusahaan Harman International dan penyedia global terkemuka teknologi inovatif untuk sistem tertanam, termasuk middleware, alat pengembangan, dan Sistem operasi. Berdasarkan arsitektur modular, QNX® Neutrino® RTOS, QNX Momentics® Development Kit, dan middleware QNX Aviage® menyediakan rangkaian perangkat lunak yang paling kuat dan dapat diskalakan untuk membangun sistem tertanam berkinerja tinggi. Perusahaan global terkemuka seperti Cisco, Daimler, General Electric, Lockheed Martin, dan Siemens secara luas menggunakan teknologi QNX di router jaringan, perangkat medis, unit telematika kendaraan, sistem keselamatan dan keamanan, robot industri, dan aplikasi penting dan kritis lainnya. tugas. Kantor pusat perusahaan berlokasi di Ottawa (Kanada), dan distributor produk berlokasi di lebih dari 100 negara di seluruh dunia.

Tentang Klocwork

Produk Klocwork dirancang untuk analisis otomatis kode statis, deteksi dan pencegahan cacat perangkat lunak dan masalah keamanan. Produk kami menyediakan alat bagi tim pengembangan untuk mengidentifikasi akar penyebab kekurangan kualitas dan keamanan perangkat lunak, serta untuk melacak dan mencegah kekurangan ini selama proses pengembangan. Didirikan pada tahun 1996, teknologi yang dipatenkan Klocwork telah memberikan pengembalian investasi (ROI) yang tinggi untuk lebih dari 80 klien, banyak di antaranya adalah perusahaan Fortune 500 dan menawarkan lingkungan pengembangan perangkat lunak yang paling dicari di dunia. Klocwork adalah perusahaan swasta dengan kantor di Burlington, San Jose, Chicago, Dallas (AS) dan Ottawa (Kanada).