Standar C ++ rusak dalam cara-cara penting. Sayangnya, alih-alih melindungi pengguna dari masalah ini, pengembang GCC telah memilih untuk menggunakan perilaku tidak terdefinisi sebagai alasan untuk menerapkan optimisasi marjinal, bahkan ketika telah jelas dijelaskan kepada mereka betapa berbahayanya itu.
Di sini orang yang jauh lebih pintar daripada yang saya jelaskan dengan sangat terperinci. (Dia berbicara tentang C tetapi situasinya sama di sana).
Mengapa itu berbahaya?
Cukup mengkompilasi ulang kode yang sebelumnya berfungsi, kode aman dengan versi yang lebih baru dari kompiler dapat memperkenalkan kerentanan keamanan . Sementara perilaku baru dapat dinonaktifkan dengan flag, makefile yang ada tidak memiliki set flag itu, jelas. Dan karena tidak ada peringatan yang dihasilkan, tidak jelas bagi pengembang bahwa perilaku yang sebelumnya masuk akal telah berubah.
Dalam contoh ini, pengembang telah menyertakan pemeriksaan untuk integer overflow, menggunakan assert
, yang akan menghentikan program jika disediakan panjang yang tidak valid. Tim GCC menghapus cek dengan dasar bahwa integer overflow tidak terdefinisi, oleh karena itu cek dapat dihapus. Ini menghasilkan contoh nyata nyata basis kode ini yang dibuat kembali menjadi rentan setelah masalah diperbaiki.
Baca semuanya. Cukup membuat Anda menangis.
OK, tapi bagaimana dengan yang ini?
Jauh ketika, ada idiom yang cukup umum yang berbunyi seperti ini:
OPAQUEHANDLE ObjectType::GetHandle(){
if(this==NULL)return DEFAULTHANDLE;
return mHandle;
}
void DoThing(ObjectType* pObj){
osfunction(pObj->GetHandle(), "BLAH");
}
Jadi idiomanya adalah: Jika pObj
bukan nol, Anda menggunakan pegangan yang dikandungnya, jika tidak, Anda menggunakan pegangan bawaan. Ini diringkas dalam GetHandle
fungsi.
Kuncinya adalah bahwa memanggil fungsi non-virtual sebenarnya tidak menggunakan this
pointer, jadi tidak ada pelanggaran akses.
Saya masih belum mengerti
Ada banyak kode yang ditulis seperti itu. Jika seseorang hanya mengkompilasi ulang, tanpa mengubah saluran, setiap panggilan DoThing(NULL)
adalah bug yang menabrak - jika Anda beruntung.
Jika Anda tidak beruntung, panggilan ke bug yang menabrak menjadi kerentanan eksekusi jarak jauh.
Ini dapat terjadi bahkan secara otomatis. Anda punya sistem build otomatis, kan? Meng-upgrade ke kompiler terbaru tidak berbahaya, bukan? Tapi sekarang tidak - tidak jika kompiler Anda adalah GCC.
Baiklah, beri tahu mereka!
Mereka sudah diberitahu. Mereka melakukan ini dengan pengetahuan penuh tentang konsekuensinya.
tapi kenapa?
Siapa yang bisa bilang? Mungkin:
- Mereka menghargai kemurnian ideal bahasa C ++ di atas kode aktual
- Mereka percaya orang harus dihukum karena tidak mengikuti standar
- Mereka tidak memiliki pemahaman tentang realitas dunia
- Mereka ... memperkenalkan bug dengan sengaja. Mungkin untuk pemerintah asing. Dimana kamu tinggal? Semua pemerintah asing bagi sebagian besar dunia, dan sebagian besar bermusuhan dengan sebagian dunia.
Atau mungkin sesuatu yang lain. Siapa yang bisa bilang?