Tim kami memberikan dukungan pelanggan yang cepat dan efisien. Hanya pemrogram yang mengambil bagian dalam dukungan, karena pemrogram juga mengajukan pertanyaan dan kami harus memikirkan banyak dari mereka. Saya ingin menggambarkan salah satu panggilan dukungan baru-baru ini tentang masalah positif palsu, yang mengarah ke studi kecil seluruh masalah yang dijelaskan dalam surat itu.
Kami bekerja keras untuk mengurangi jumlah positif palsu yang dihasilkan oleh alat analisa PVS-Studio. Sayangnya, penganalisa statis sering tidak dapat membedakan kode yang benar dari kesalahan, karena mereka tidak memiliki informasi yang cukup. Akibatnya, ada positif palsu pula. Namun, ini bukan masalah, karena setelah menyetel alat analisa, mudah untuk mencapai situasi di mana
9 dari 10 peringatan akan menunjukkan kesalahan nyata.
Meskipun alarm palsu bukan masalah besar seperti yang terlihat pada pandangan pertama, kami terus berjuang dengan mereka, meningkatkan diagnosa. Kami melihat sendiri beberapa false positive yang positif, beberapa di antaranya dituliskan kepada kami oleh pelanggan dan pengguna gratis.
Baru-baru ini, salah satu klien kami menulis surat kira-kira konten berikut:
Untuk beberapa alasan, penganalisa mengatakan bahwa pointer selalu nol, walaupun ini jelas tidak begitu. Selain itu, penganalisa bertingkah aneh dan tidak stabil pada proyek uji: baik memberikan peringatan, atau tidak. Contoh sintetis yang mereproduksi false positive:#include <windows.h> #include <aclapi.h> #include <tchar.h> int main() { PACL pDACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; ::GetNamedSecurityInfo(_T("ObjectName"), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &pSD); auto test = pDACL == NULL; // V547 Expression 'pDACL == 0' is always true. return 0; }
Saya bisa membayangkan bagaimana tanggapan serupa terlihat dari pengguna kami. Segera dihapus bahwa fungsi
GetNamedSecurityInfo mengubah nilai variabel
pDACL . Mungkinkah pengembang tidak dapat menulis handler untuk situasi yang begitu sederhana? Selain itu, tidak jelas mengapa penganalisa baik mengeluarkan pesan atau tidak. Mungkin mereka sendiri memiliki semacam bug di alat, seperti variabel yang tidak diinisialisasi?
Eh ... Ini bukan pekerjaan mudah untuk memelihara penganalisa kode statis. Tapi apa yang harus dilakukan, saya sendiri memilih nasib seperti itu. Sambil menyingsingkan lengan baju saya, saya melanjutkan untuk menyelidiki penyebab positif palsu.
Untuk mulai dengan, saya mempelajari deskripsi fungsi
GetNamedSecurityInfo dan memastikan bahwa panggilannya harus benar-benar mengarah pada perubahan nilai variabel
pDACL . Berikut adalah deskripsi argumen fungsi ke-6:
ppdacl
Pointer ke variabel yang menerima pointer ke DACL di deskriptor keamanan yang dikembalikan atau NULL jika deskriptor keamanan tidak memiliki DACL. Pointer yang dikembalikan hanya valid jika Anda menetapkan flag DACL_SECURITY_INFORMATION. Juga, parameter ini bisa NULL jika Anda tidak membutuhkan DACL.
|
Saya tahu bahwa penganalisa PVS-Studio harus benar-benar memproses kode sederhana seperti itu dan tidak memberikan peringatan yang tidak berarti. Sudah pada saat ini, intuisi saya mengatakan kepada saya bahwa ini akan menjadi kasus yang tidak biasa, yang harus menghabiskan waktu.
Saya mengkonfirmasi ketakutan saya ketika saya tidak bisa mereproduksi positif palsu baik pada versi alpha saat ini dari penganalisa, atau tepatnya pada versi yang diinstal pada klien. Begitu dan begitu, tetapi penganalisa diam.
Saya meminta klien untuk mengirim saya
file-i preproses yang dihasilkan untuk sebuah program dengan contoh sintetis. Dia menghasilkan, mengirim file, dan saya mulai memeriksanya secara rinci.
Pada file yang dikirim, alat analisa segera mengeluarkan false positive. Di satu sisi, ini bagus, karena bug direproduksi. Di sisi lain, saya mengalami perasaan yang digambarkan oleh gambar ini.
Kenapa ini? Saya tahu betul bagaimana alat analisa dan diagnostik
V547 bekerja . Yah, tidak mungkin ada aktuasi seperti itu!
Ok, buat teh dan lanjutkan.
Panggilan ke fungsi
GetNamedSecurityInfo meluas ke:
::GetNamedSecurityInfoW(L"ObjectName", SE_FILE_OBJECT, (0x00000004L), 0, 0, &pDACL, 0, &pSD);
Kode ini terlihat sama baik di file-i preprocessed saya sendiri dan dalam file yang dikirim oleh klien.
Hmm ... Oke, sekarang kita akan memeriksa bagaimana fungsi ini dinyatakan. Dalam file saya, saya melihat:
__declspec(dllimport) DWORD __stdcall GetNamedSecurityInfoW( LPCWSTR pObjectName, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, PSID * ppsidOwner, PSID * ppsidGroup, PACL * ppDacl, PACL * ppSacl, PSECURITY_DESCRIPTOR * ppSecurityDescriptor );
Semuanya logis, semuanya jelas. Tidak ada yang tak terduga.
Selanjutnya, saya melihat file klien dan ...
Di sana saya melihat sesuatu dari realitas paralel:
__declspec(dllimport) DWORD __stdcall GetNamedSecurityInfoW( LPCWSTR pObjectName, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, const PSID * ppsidOwner, const PSID * ppsidGroup, const PACL * ppDacl, const PACL * ppSacl, PSECURITY_DESCRIPTOR * ppSecurityDescriptor );
Perhatikan bahwa argumen formal ke
ppDacl ditandai sebagai
const .
Wat? WTF? Wat? WTF?Apa yang
const !? Dari mana asalnya !?
Setidaknya segera jelas bahwa penganalisa tidak bisa disalahkan di sini dan saya dapat mempertahankan kehormatannya.
Argumennya adalah pointer ke objek konstan. Ternyata, dari sudut pandang
penganalisa, fungsi
GetNamedSecurityInfoW tidak dapat mengubah objek yang
dirujuk oleh pointer. Oleh karena itu di sini:
PACL pDACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; ::GetNamedSecurityInfo(_T("ObjectName"), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &pSD); auto test = pDACL == NULL;
variabel
pDACL tidak dapat berubah dan penganalisis menghasilkan peringatan yang masuk akal (Ekspresi 'pDACL == 0' selalu benar.).
Mengapa peringatan dikeluarkan bisa dimengerti. Tetapi tidak jelas dari mana asal
const ini. Itu tidak mungkin ada di sana!
Namun, ada dugaan, dan itu dikonfirmasi oleh pencarian di Internet. Ternyata ada file aclapi.h lama yang tidak valid dengan deskripsi fungsi yang salah. Saya juga menemukan dua tautan menarik di Internet:
Jadi, suatu ketika ada deskripsi fungsi dalam file aclapi.h (6.0.6002.18005-Windows 6.0):
WINADVAPI DWORD WINAPI GetNamedSecurityInfoW( __in LPWSTR pObjectName, __in SE_OBJECT_TYPE ObjectType, __in SECURITY_INFORMATION SecurityInfo, __out_opt PSID * ppsidOwner, __out_opt PSID * ppsidGroup, __out_opt PACL * ppDacl, __out_opt PACL * ppSacl, __out_opt PSECURITY_DESCRIPTOR * ppSecurityDescriptor );
Kemudian seseorang ingin memperbaiki jenis argumen resmi
pObjectName , tetapi sepanjang jalan mengacaukan jenis pointer dengan menulis
const . Dan aclapi.h (6.1.7601.23418-Windows 7.0) menjadi seperti ini:
WINADVAPI DWORD WINAPI GetNamedSecurityInfoW( __in LPCWSTR pObjectName, __in SE_OBJECT_TYPE ObjectType, __in SECURITY_INFORMATION SecurityInfo, __out_opt const PSID * ppsidOwner, __out_opt const PSID * ppsidGroup, __out_opt const PACL * ppDacl, __out_opt const PACL * ppSacl, __out PSECURITY_DESCRIPTOR * ppSecurityDescriptor );
Menjadi jelas bahwa justru file aclapi.h yang salah salah yang digunakan oleh klien. Dia kemudian mengkonfirmasi hipotesis ini dalam korespondensi. Saya menggunakan versi yang lebih baru, sehingga kesalahan tidak mereproduksi.
Berikut ini uraian fungsi yang sudah diperbaiki di aclapi.h (6.3.9600.17415-Windows_8.1).
WINADVAPI DWORD WINAPI GetNamedSecurityInfoW( _In_ LPCWSTR pObjectName, _In_ SE_OBJECT_TYPE ObjectType, _In_ SECURITY_INFORMATION SecurityInfo, _Out_opt_ PSID * ppsidOwner, _Out_opt_ PSID * ppsidGroup, _Out_opt_ PACL * ppDacl, _Out_opt_ PACL * ppSacl, _Out_ PSECURITY_DESCRIPTOR * ppSecurityDescriptor );
Tipe argumen
pObjectName tetap sama, tetapi
const tambahan dihapus. Semuanya telah kembali ke tempatnya masing-masing, tetapi file header dengan deklarasi fungsi yang salah terus hidup di dunia.
Semua ini saya beri tahu klien. Dia senang dan senang bahwa situasi telah beres. Selain itu, ia menemukan alasan mengapa ia melihat positif palsu atau tidak:
Saya lupa bahwa saya pernah bereksperimen dengan peralatan pada proyek pengujian ini. Dalam proyek pengujian Debug, konfigurasi dikonfigurasikan pada Platform Toolset secara default untuk Visual Studio 2017 - "Visual Studio 2017 (v141)", tetapi konfigurasi Rilis dikonfigurasikan pada "Visual Studio 2015 - Windows XP (v140_xp)". Kemarin, saya baru saja mengubah konfigurasi, dan peringatan itu muncul dan menghilang.Itu saja. Anda dapat mengakhiri penyelidikan. Kami memutuskan dengan klien bahwa kami tidak akan membuat cadangan khusus apa pun dalam penganalisa sehingga bug ini dimasukkan ke dalam file header. Yang utama adalah bahwa situasinya sekarang jelas. Seperti kata pepatah, "kasing ditutup."
KesimpulanPVS-Studio analyzer adalah produk perangkat lunak kompleks yang mengumpulkan banyak informasi dari kode program dan menggunakannya untuk berbagai
teknologi analisis . Secara khusus, dalam kasus ini, kecerdasan berlebihan dari penganalisa telah mengarah pada fakta bahwa, karena deskripsi fungsi yang salah, ia mulai menghasilkan false positive.
Menjadi pelanggan kami dan Anda akan menerima dukungan cepat dan berkualitas dari saya dan kolega saya.
Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Andrey Karpov.
Positif Salah di PVS-Studio: Seberapa Jauh Lubang Kelinci Berlangsung .