Bagikan melalui


AddressSanitizer runtime

Pustaka runtime AddressSanitizer mencegat fungsi dan operasi alokasi memori umum untuk memungkinkan inspeksi akses memori. Ada beberapa pustaka runtime berbeda yang mendukung berbagai jenis executable yang dapat dihasilkan pengkompilasi. Pengkompilasi dan linker secara otomatis menautkan pustaka runtime yang sesuai, selama Anda meneruskan opsi pada /fsanitize=address waktu kompilasi. Anda dapat mengambil alih perilaku default dengan menggunakan opsi pada /NODEFAULTLIB waktu tautan. For more information, see the section on linking in the AddressSanitizer language, build, and debugging reference.

When compiling with cl /fsanitize=address, the compiler generates instructions to manage and check shadow bytes. Program Anda menggunakan instrumentasi ini untuk memeriksa akses memori pada tumpukan, dalam tumpukan, atau dalam cakupan global. Pengkompilasi juga menghasilkan metadata yang menjelaskan tumpukan dan variabel global. Metadata ini memungkinkan runtime untuk menghasilkan diagnostik kesalahan yang tepat: nama fungsi, baris, dan kolom dalam kode sumber Anda. Dikompilasi, pemeriksaan kompilator dan pustaka runtime dapat dengan tepat mendiagnosis banyak jenis bug keamanan memori jika ditemui pada run-time.

Daftar pustaka runtime untuk menautkan ke runtime AddressSanitizer, pada Visual Studio 17.7 Pratinjau 3, berikut. Untuk informasi selengkapnya tentang /MT opsi (secara statis menautkan runtime) dan /MD (secara dinamis menautkan redist saat runtime), lihat opsi /MD, /MT, /LD (Gunakan Pustaka Run-Time).

Note

Dalam tabel berikut, {arch} adalah i386 atau x86_64. Pustaka ini menggunakan konvensi Clang untuk nama arsitektur. Konvensi MSVC biasanya x86 dan bukan x64 dan i386x86_64, tetapi mengacu pada arsitektur yang sama.

CRT option Pustaka runtime AddressSanitizer (.lib) Biner runtime alamat (.dll)
/MT atau /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD atau /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

Diagram berikut menunjukkan bagaimana pustaka runtime bahasa ditautkan untuk /MTopsi , , /MTd/MD, dan /MDd pengkompilasi:

Diagram bagaimana pustaka runtime ditautkan untuk berbagai opsi pengkompilasi.

Gambar menunjukkan tiga skenario untuk menautkan pustaka runtime. Yang pertama adalah /MT atau /MTd. My_exe.exe dan my_dll.dll keduanya ditampilkan dengan salinan VCRuntime yang ditautkan secara statis, Universal CRT, dan runtime C++. Skenario menunjukkan /MD di mana my_exe.exe dan my_dll.dll berbagi vcruntime140.dll, ucrtbase.dll, dan msvcp140.dll. Skenario terakhir menunjukkan /MDd di mana my_exe.exe dan my_dll.dll berbagi versi debug runtime: vcruntime140d.dll, ucrtbased.dll, dan msvcp140d.dll

Diagram berikut menunjukkan bagaimana pustaka ASan ditautkan untuk berbagai opsi pengkompilasi:

Diagram bagaimana dll runtime ASan ditautkan.

Gambar menunjukkan empat skenario untuk menautkan pustaka runtime ASan. Skenarionya adalah untuk /MT (secara statis menautkan runtime), /MTd (secara statis menautkan runtime debug), /MD (secara dinamis menautkan redist pada runtime), /MDd (secara dinamis menautkan redist debug saat runtime). Dalam semua kasus, my_exe.exe tautan dan rekannya my_dll.dll tautan ke satu instans clang-rt.asan-dynamix-x86_64.dll.

Bahkan ketika menautkan secara statis, DLL runtime ASan harus ada pada runtime--tidak seperti komponen C Runtime lainnya.

Previous versions

Sebelum Visual Studio 17.7 Pratinjau 3, build yang ditautkan secara statis (/MT atau /MTd) tidak menggunakan dependensi DLL. Sebagai gantinya, runtime AddressSanitizer secara statis ditautkan ke EXE pengguna. Proyek DLL kemudian akan memuat ekspor dari EXE pengguna untuk mengakses fungsionalitas ASan.

Proyek yang ditautkan secara dinamis (/MD atau /MDd) menggunakan pustaka dan DLL yang berbeda tergantung pada apakah proyek dikonfigurasi untuk debug atau rilis. Untuk informasi selengkapnya tentang perubahan ini dan motivasinya, lihat MSVC Address Sanitizer – One DLL untuk semua Konfigurasi Runtime.

Tabel berikut ini menjelaskan perilaku sebelumnya dari penautan pustaka runtime AddressSanitizer, sebelum Pratinjau Visual Studio 17.7 3:

CRT option DLL atau EXE DEBUG? Pustaka ASan (.lib) Biner runtime ASan (.dll)
/MT EXE No clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} None
/MT DLL No clang_rt.asan_dll_thunk-{arch} None
/MD Either No clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MT EXE Yes clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} None
/MT DLL Yes clang_rt.asan_dbg_dll_thunk-{arch} None
/MD Either Yes clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} clang_rt.asan_dbg_dynamic-{arch}

Diagram berikut menunjukkan bagaimana pustaka ASan ditautkan untuk berbagai opsi pengkompilasi sebelum Visual Studio 2022 17.7 Pratinjau 3:

Diagram bagaimana dll runtime ASan ditautkan sebelum Visual Studio 2022 Pratinjau 3.

Gambar menunjukkan empat skenario untuk menautkan pustaka runtime ASan. Skenarionya adalah untuk /MT (secara statis menautkan runtime), /MTd (secara statis menautkan runtime debug), /MD (secara dinamis menautkan redist pada runtime), /MDd (secara dinamis menautkan redist debug saat runtime). Untuk /MT, my_exe.exe memiliki salinan runtime ASan yang ditautkan secara statis. my_dll.dll tautan ke runtime ASan di my_exe.exe. Untuk /MTd, diagramnya sama kecuali menggunakan runtime ASan yang ditautkan secara statis debug. Untuk /MD, baik tautan my_exe.exe dan my_dll.dll ke runtime ASan yang ditautkan secara dinamis bernama clang_rt.asan_dynamic-x86_64.dll. Untuk /MDd, diagramnya sama kecuali tautan my_exe.exe dan my_dll.dll ke runtime ASan debug bernama clang_rt.asan_dbg_dynamic-x86_64.dll.

Function interception

AddressSanitizer mencapai intersepsi fungsi melalui banyak teknik hotpatching. Teknik ini paling baik didokumenkan dalam kode sumber itu sendiri.

Pustaka runtime mencegat banyak manajemen memori umum dan fungsi manipulasi memori. Untuk daftar, lihat Daftar AddressSanitizer fungsi yang disadap. Pencegat alokasi mengelola metadata dan byte bayangan yang terkait dengan setiap panggilan alokasi. Setiap kali fungsi CRT seperti malloc atau delete dipanggil, pencegat menetapkan nilai tertentu di wilayah memori bayangan AddressSanitizer untuk menunjukkan apakah lokasi timbunan tersebut saat ini dapat diakses dan apa batas alokasinya. These shadow bytes allow the compiler-generated checks of the shadow bytes to determine whether a load or store is valid.

Intersepsi tidak dijamin berhasil. Jika prolog fungsi terlalu singkat untuk jmp ditulis, penyadapan dapat gagal. Jika kegagalan intersepsi terjadi, program akan melempar debugbreak dan menghentikan. Jika Anda melampirkan debugger, itu membuat penyebab masalah intersepsi menjadi jelas. Jika Anda memiliki masalah ini, laporkan bug.

Note

Pengguna dapat secara opsional mencoba untuk melanjutkan melewati intersepsi yang gagal dengan mengatur variabel ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE lingkungan ke nilai apa pun. Melanjutkan melewati kegagalan intersepsi dapat mengakibatkan laporan bug yang terlewat untuk fungsi tersebut.

Alokator kustom dan runtime AddressSanitizer

Runtime AddressSanitizer menyediakan pencegat untuk antarmuka alokator umum, , malloc/free, new/deleteHeapAlloc/HeapFree(melalui ).RtlAllocateHeap/RtlFreeHeap Banyak program menggunakan alokator kustom karena satu alasan atau lainnya, contohnya adalah program apa pun yang menggunakan dlmalloc atau solusi menggunakan std::allocator antarmuka dan VirtualAlloc(). Pengkompilasi tidak dapat secara otomatis menambahkan panggilan manajemen memori bayangan ke alokator kustom. Pengguna bertanggung jawab untuk menggunakan antarmuka keracunan manual yang disediakan. This API enables these allocators to function properly with the existing AddressSanitizer runtime and shadow byte conventions.

Antarmuka keracunan AddressSanitizer Manual

Antarmuka untuk pencerahan sederhana, tetapi memberlakukan pembatasan penyelarasan pada pengguna. Pengguna dapat mengimpor prototipe ini dengan mengimpor sanitizer/asan_interface.h. Berikut adalah prototipe fungsi antarmuka:

void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

Untuk kenyamanan, file header antarmuka AddressSanitizer menyediakan makro pembungkus. Makro ini memeriksa apakah fungsionalitas AddressSanitizer diaktifkan selama kompilasi. Mereka memungkinkan kode sumber Anda untuk menghilangkan panggilan fungsi keracunan saat tidak diperlukan. Makro ini harus lebih disukai daripada memanggil fungsi di atas secara langsung:

#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)

Note

Jika Anda meracuni memori secara manual, Anda harus membukanya sebelum digunakan kembali. Ini sangat penting untuk alamat tumpukan, seperti untuk variabel lokal, yang sering digunakan kembali selama eksekusi program. Anda berisiko memperkenalkan use-after-poison positif palsu dalam alamat tumpukan yang diracuni secara manual jika Anda tidak melepasnya sebelum bingkai tumpukannya dihapus.

Persyaratan penyelarasan untuk keracunan AddressSanitizer

Setiap keracunan manual byte bayangan harus mempertimbangkan persyaratan penyelarasan. Pengguna harus menambahkan padding jika perlu sehingga byte bayangan berakhir pada batas byte dalam memori bayangan. Setiap bit dalam memori bayangan AddressSanitizer mengodekan status byte tunggal dalam memori aplikasi. Pengodean ini berarti ukuran total setiap alokasi, termasuk padding apa pun, harus selaras dengan batas 8 byte. Jika persyaratan penyelarasan tidak terpenuhi, persyaratan tersebut dapat menyebabkan pelaporan bug yang salah. Pelaporan yang salah dapat bermanifestasi sebagai laporan yang hilang (negatif palsu) atau laporan tentang non-kesalahan (positif palsu).

Untuk ilustrasi persyaratan perataan dan potensi masalah, lihat contoh perataan ASan yang disediakan. Salah satunya adalah program kecil untuk menunjukkan apa yang bisa salah dengan keracunan memori bayangan manual. Yang kedua adalah contoh implementasi keracunan manual menggunakan std::allocator antarmuka.

Runtime options

MSVC AddressSanitizer didasarkan pada runtime Clang AddressSanitizer dari repositori llvm-project. Karena itu, sebagian besar opsi runtime bahasa umum ASan clang juga tersedia di MSVC. Daftar lengkap opsi runtime Clang publik tersedia di sini. Kami mendokumen beberapa perbedaan di bagian berikut. Jika Anda menemukan opsi yang tidak berfungsi seperti yang diharapkan, laporkan bug.

Mengonfigurasi opsi runtime

Opsi runtime ASan diatur dalam salah satu dari dua cara:

  • Variabel ASAN_OPTIONS lingkungan
  • Fungsi __asan_default_options pengguna

Jika variabel lingkungan dan fungsi pengguna menentukan opsi yang bertentangan, opsi dalam ASAN_OPTIONS variabel lingkungan diutamakan.

Beberapa opsi ditentukan dengan memisahkannya dengan titik dua (:).

Contoh berikut diatur alloc_dealloc_mismatch ke satu dan symbolize ke nol:

set ASAN_OPTIONS=alloc_dealloc_mismatch=1:symbolize=0

Atau tambahkan fungsi berikut ke kode Anda:

extern "C" const char* __asan_default_options()
{
  return "alloc_dealloc_mismatch=1:symbolize=0";
}

Opsi AddressSanitizer yang tidak didukung

  • detect_container_overflow
  • unmap_shadow_on_exit

Note

Opsi halt_on_error runtime AddressSanitizer tidak berfungsi seperti yang mungkin Anda harapkan. In both the Clang and the MSVC runtime libraries, many error types are considered non-continuable, including most memory corruption errors.

Untuk informasi selengkapnya, lihat bagian Perbedaan dengan Clang 12.0 .

Opsi runtime AddressSanitizer khusus MSVC

  • continue_on_error Boolean, atur ke false secara default. Ketika diatur ke true, ini memungkinkan program untuk terus mengeksekusi setelah pelanggaran memori dilaporkan, memungkinkan Anda untuk mengumpulkan beberapa laporan kesalahan.

  • iat_overwrite String, diatur ke "error" secara default. Nilai lain yang mungkin adalah "protect" dan "ignore". Beberapa modul dapat menimpa import address table modul lain untuk menyesuaikan implementasi fungsi tertentu. Misalnya, driver biasanya menyediakan implementasi kustom untuk perangkat keras tertentu. Opsi iat_overwrite mengelola perlindungan runtime AddressSanitizer terhadap penimpaan untuk fungsi tertentu memoryapi.h . Runtime saat ini melacak VirtualAllocfungsi , VirtualProtect, dan VirtualQuery untuk perlindungan. Opsi ini tersedia di Visual Studio 2022 versi 17.5 Pratinjau 1 dan versi yang lebih baru. Nilai berikut iat_overwrite mengontrol bagaimana runtime bereaksi saat fungsi yang dilindungi ditimpa:

    • Jika diatur ke "error" (default), runtime melaporkan kesalahan setiap kali penimpaan terdeteksi.
    • Jika diatur ke "protect", runtime mencoba menghindari penggunaan definisi yang ditimpa dan melanjutkan. Secara efektif, definisi asli memoryapi fungsi digunakan dari dalam runtime untuk menghindari rekursi tak terbatas. Modul lain dalam proses masih menggunakan definisi yang ditimpa.
    • Jika diatur ke "ignore", runtime tidak mencoba memperbaiki fungsi yang ditimpa dan melanjutkan eksekusi.
  • windows_fast_fail_on_error Boolean (false secara default), atur ke true untuk mengaktifkan proses untuk mengakhiri dengan __fastfail(71) setelah mencetak laporan kesalahan.

Note

Ketika nilai abort_on_error diatur ke true, pada Windows program berakhir dengan exit(3). Agar tidak mengubah perilaku saat ini, kami memutuskan untuk memperkenalkan opsi baru ini sebagai gantinya. Jika abort_on_error dan windows_fast_fail_on_error benar, program akan keluar dengan __fastfail.

  • windows_hook_legacy_allocators Boolean, atur ke false untuk menonaktifkan intersepsi GlobalAlloc dan LocalAlloc alokator.

    Note

    Opsi windows_hook_legacy_allocators ini tidak tersedia di runtime proyek llvm publik saat artikel ini ditulis. Opsi pada akhirnya dapat dikontribusikan kembali ke proyek publik; namun, itu tergantung pada tinjauan kode dan penerimaan komunitas.

    Opsi windows_hook_rtl_allocators, sebelumnya fitur keikutsertaan saat AddressSanitizer bersifat eksperimental, sekarang diaktifkan secara default. Dalam versi sebelum Visual Studio 2022 versi 17.4.6, nilai opsi defaultnya adalah false. Di Visual Studio 2022 versi 17.4.6 dan versi yang lebih baru, opsi windows_hook_rtl_allocators default ke true.

Daftar AddressSanitizer dari fungsi yang dicegat (Windows)

Runtime AddressSanitizer melakukan hotpatch pada banyak fungsi untuk mengaktifkan pemeriksaan keamanan memori pada runtime. Berikut adalah daftar fungsi yang tidak lengkap yang dipantau runtime AddressSanitizer.

Default interceptors

Optional interceptors

Pencegat yang tercantum di sini hanya diinstal ketika opsi runtime AddressSanitizer diaktifkan. Atur windows_hook_legacy_allocators ke false untuk menonaktifkan intersepsi alokator warisan. set ASAN_OPTIONS=windows_hook_legacy_allocators=false

See also

AddressSanitizer overview
Masalah yang diketahui AddressSanitizer
Referensi bahasa dan build AddressSanitizer
Byte bayangan AddressSanitizer
AddressSanitizer cloud atau pengujian terdistribusi
Integrasi debugger AddressSanitizer
Contoh kesalahan AddressSanitizer