|
|
Diposting pada 31/07/2023 18.36.01
|
|
|
|

Suatu pagi yang cerah, saya sedang duduk di depan laptop saya merestrukturisasi beberapa kode C#. Semuanya berjalan dengan baik dan ini akan menjadi hari yang produktif. Kemudian saya menambahkan terlalu banyak tanda sama dengan literal string konstan, dan semuanya meledak. Produktivitas hilang. Rekonstruksi tenang hari Minggu sudah berlalu. Bahkan matahari memutuskan untuk bersembunyi di balik awan.
Setelah menghabiskan 30 hingga 40 menit mencoba mencari tahu apa yang saya lakukan salah, saya menyadari bahwa itu bukan saya. Ini Microsoft. Rupanya, saya menemukan bug lama dalam fungsi decoding Base64.Konversi.DariBase64StringBug ini pasti sudah ada sejak .NET 1.1 diperkenalkan pada tahun 2003. Wow! Itu sudah tua. Dan tidak terlalu sulit untuk mereproduksi. Kerja yang bagus:
Secara teknis, ini adalah Base64 ilegal. Versi legalnya adalah "abc=". Perhatikan hanya satu karakter pengisi =. Pengkodean Base64 mewakili setiap 6 bit input biner dalam satu karakter ASCII. Ini berarti bahwa setiap 4 karakter dalam string yang dikodekan Base64 mewakili 3 byte. Ketika data yang dikodekan bukan kelipatan 3 byte, encoder Base64 menambahkan karakter pengisi untuk membuat Base64 kelipatan 4 karakter. Ini akan menghasilkan string Base64 yang diisi dengan benar dengan "abc=". Menambahkan yang lain = akan membatalkannya.
Base64 "abc=" didekodekan sebagai dua byte [105, 183]. Itu benar. Menambahkan karakter padding lain di akhir seharusnya tidak benar-benar mengubah nilai yang dikodekan. Ini seperti menambahkan spasi di akhir kalimat. Ya, itu ada, tetapi itu tidak mengubah arti kalimat. Tapi .NET tidak berpikir demikian. "abc==" didekodekan sebagai byte [109]. Tidak hanya menjadi lebih pendek, yang aneh karena kami membuat input lebih lama. Itu juga menjadi berbeda. Byte pertama berkisar dari 105 menjadi 109. Dan itu juga tidak memberikan pengecualian. Tambahkan = lain dan Anda mendapatkan pengecualian. Menakjubkan!
Kode:
Hasil:
'abc=' -> [105, 183] 'abc==' -> [109] Sungguh menakjubkan bahwa tidak ada yang memperhatikan ini selama bertahun-tahun. Atau ditemukan tetapi tidak diperbaiki. Base64 sangat penting dalam pertukaran informasi di jaringan. Itu bisa dilihat di mana-mana. Namun, .NET belum menyingkirkan dekoder Base64 yang cacat selama bertahun-tahun.
Awalnya saya tidak bisa mempercayainya dan mulai menyelidiki. Saya mencari di Google sebentar dan tidak menemukan banyak. Kemudian saya memposting di StackOverflow dan juga tidak mendapatkan banyak keberuntungan. Begitu saya mengetahui apa yang sedang terjadi, saya bahkan harus menjawab pertanyaan saya sendiri. Setelah mencari di GitHub sebentar, saya menemukan perbaikan yang dibuat di .NET Core pada Juli 2018. Jadi versi .NET Core terbaru menangani masalah ini dengan benar dan melemparkan pengecualian:
Pengecualian yang Tidak Ditangani: System.FormatException: Input bukanlah string Base-64 yang valid karena berisi karakter 64 non-dasar, lebih dari dua karakter padding, atau karakter ilegal di antara Karakter padding. di System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) di System.Convert.FromBase64String(String s) di Program.DecodeAndPrint(String base64) di ./base64/Program.cs:baris 13 di Program.Main() di ./base64/Program.cs:baris 8 Mereka membutuhkan waktu sekitar 15 tahun untuk menemukan dan memperbaiki masalah. Menariknya, tidak ada yang benar-benar mencoba memperbaikinya secara khusus. Ini terjadi ketika mereka menulis ulang kode untuk membuatnya lebih cepat:
Convert.FromBase64() memiliki bug halus di mana karakter kedua yang dilapisi secara ilegal di akhir string menyebabkan decoding "berhasil" dengan menghapus karakter kedua dari belakang.
Kami berada di . Bug ini secara tidak sengaja diperbaiki saat API dioptimalkan di NetCore 2.1. Tambahkan pengujian ke kesalahan log dan pastikan kita tidak mundur. Jadi masalah ini diperbaiki di .NET Core 2.2. Tetapi dalam versi terbaru .NET Framework 4.7.2 saat ini masih memiliki masalah. Sepertinya rusak di Mono juga.
Solusinya di .NET 4.7.2 adalah mengisi ulang string yang salah terisi dengan sesuatu seperti ini:
Asli:Login hyperlink terlihat.
|
Mantan:Azure DevOps (viii) Mengkompilasi proyek MVC ASP.NET menggunakan Pipelines BuildDepan:Pengatur waktu baru di .NET 6, PeriodicTimer, digunakan
|