Linux hapus API `strncpy` setelah 6 tahun dan lebih dari 360 patch
(phoronix.com/news)- Di Linux 7.2, penggunaan API
strncpydi dalam kernel telah hilang, sehingga antarmuka penyalinan string yang sejak lama dijadwalkan untuk dihentikan akhirnya dihapus sepenuhnya strncpy()menyalin sebanyak jumlah byte yang ditentukan, tetapi perilaku terminasi NUL-nya tidak intuitif sehingga selama bertahun-tahun tetap menjadi sumber bug di kernel- Karakteristiknya yang mengisi buffer tujuan dengan 0 secara tidak perlu bahkan menimbulkan masalah performa, dan butuh sekitar 6 tahun serta 362 commit untuk menyingkirkannya
- Dalam merge pada hari Jumat, bukan hanya API utamanya yang dihapus, tetapi juga implementasi spesifik arsitektur per-CPU yang terakhir
- Kode kernel kini harus memilih fungsi pengganti sesuai kebutuhan, seperti
strscpy(),strscpy_pad(),strtomem_pad(),memcpy_and_pad(), danmemcpy()
strncpy yang menghilang di Linux 7.2
- Linux 7.2 akhirnya menghapus API
strncpyyang sejak lama direncanakan untuk dihentikan dari kernel - Setelah pekerjaan pembersihan selama 6 tahun, kini tidak ada lagi kode internal kernel yang menggunakan antarmuka
strncpy - Perubahan ini bukan sekadar penggantian fungsi, melainkan lebih mendekati upaya menghapus praktik penyalinan string lama di seluruh kernel
Skala pekerjaan hingga penghapusan
- Penghapusan
strncpymembutuhkan sekitar 362 commit - Pekerjaan dilakukan dengan cara menghapus penggunaan
strncpydi dalam kernel secara bertahap - Di Linux 7.2, pekerjaan pembersihan ini akhirnya mencapai titik penyelesaian
Mengapa strncpy menjadi masalah di kernel
strncpytelah lama dianggap sebagai penyebab bug yang terus berulang di dalam kernel Linux- Secara khusus, ada dua perilaku yang menjadi masalah
- Makna dan perilaku terminasi NUL tidak intuitif sehingga mudah menimbulkan kesalahan penggunaan
- Buffer tujuan diisi 0 secara berulang, sehingga menimbulkan biaya performa yang tidak perlu
Merge penghapusan yang sebenarnya
- Merge yang dilakukan pada hari Jumat menghapus API
strncpy - Dalam merge yang sama, implementasi
strncpyspesifik arsitektur per-CPU yang terakhir juga ikut dihapus
API pengganti untuk kode kernel
- Sebagai pengganti
strncpy, kini perlu memilih fungsi yang sesuai dengan target penyalinan dan kondisi terminasistrscpy(): digunakan untuk tujuan yang berakhir dengan NULstrscpy_pad(): digunakan saat tujuan berakhir dengan NUL dan membutuhkan padding 0strtomem_pad(): digunakan untuk field lebar tetap yang tidak diakhiri NULmemcpy_and_pad(): digunakan untuk penyalinan terbatas dengan padding eksplisitmemcpy(): digunakan untuk penyalinan memori saat panjangnya sudah diketahui
1 komentar
Komentar Hacker News
Dulu orang suka mengejek pengembang kernel Linux—yang katanya termasuk pengembang C terbaik di dunia—karena tidak bisa membuat tipe stringbuffer atau stringview, tetapi saat itu memang belum ada konsensus seperti sekarang soal topik ini, jadi masih bisa dimaklumi
Orang yang sudah melihat arah yang benar adalah Dennis Ritchie, yang pada 1990 mengusulkan tipe fat pointer untuk C. Itu akan menjadi tambahan yang sempurna andaikan masuk ke C99, dan kalau komite memasukkannya, dunia mungkin akan cukup berbeda
Pada 2007 sempat ada kesempatan kedua saat tulisan Walter Bright “C's greatest mistake” terbit, yang pada dasarnya menjelaskan slice/stringview dengan lebih jelas—ide yang esensinya sama dengan Ritchie—tetapi tetap tidak masuk ke C11. Sekarang pun sudah sampai C23 dan itu masih belum ada; sebagai gantinya kita mendapat _Generic dan VLA, jadi rasanya seperti ya sudahlah, pesta saja
Saat mencari-cari saya juga melihat thread Reddit tentang topik yang sama, dan debat bikeshedding-nya lucu: https://www.reddit.com/r/C_Programming/comments/90uq7c/cs_bi...
Saya penasaran kenapa perilaku array C yang meluruh menjadi pointer dirancang seperti itu. Ada penjelasan bahwa tujuannya agar kode B bisa dikompilasi ke C dengan perubahan seminimal mungkin; di B, deklarasi array ternyata benar-benar mendefinisikan pointer dan array, lalu pointer itu diinisialisasi agar menunjuk ke elemen pertama array
Masalah yang lebih besar sekarang adalah pustaka standar C masih terikat pada era K&R, dan bahkan fitur bahasa seperti argumen atau nilai balik struct yang ditambahkan di C99 pun tidak tercermin dalam API pustaka standarnya. Andai pustaka standar punya struct rentang berupa pasangan pointer/ukuran, plus fungsi string baru atau fungsi string yang diperbarui untuk memakainya, situasinya bisa jauh lebih baik
strncpy di dalam kernel Linux disebut sudah bertahun-tahun menjadi “sumber bug yang membandel” karena semantiknya yang tidak intuitif, penanganan terminasi NUL, dan masalah performa akibat mengisi tujuan dengan 0 secara tidak perlu
Setiap kali saya diminta mereview kode C, saya mencari strncpy, dan hampir selalu menemukan bug di sana
Ada hal-hal yang sudah mengganggu selama 40 tahun. String berterminasi NUL, dan sekarang bahkan string non-UTF-8 untuk I/O pun termasuk di dalamnya
Begitu juga kebiasaan menangani akhir baris sebagai LF, CR, atau CRLF, serta cara memisahkan field dengan pipa atau koma. Kalau sejak awal dipakai karakter ASCII yang tidak ambigu seperti GS, FS, dan RS, encoding/decoding akhir baris akan menjadi masalah I/O, sementara HT/VT/CR/LF/FF bisa tetap menjadi kode yang murni terkait output
Kekacauan soal penanganan escape yang biasa muncul pada data berbasis koma hilang, jadi semuanya jauh lebih sederhana
Standar Unicode mengatakan bahwa bukan hanya CR, LF, CRLF, dan karakter-karakter itu saja yang harus diperlakukan sebagai pemisah baris, tetapi juga vertical tab dan form feed
Akhir baris seperti LF, CR, dan CRLF juga merupakan konvensi sistem operasi, dan lebih baik bahasa pemrograman tidak mencoba “menebak” akhir baris yang benar. Itu menciptakan lebih banyak masalah daripada menyelesaikannya, dan sekali lagi ini kebanyakan masalah khas Windows, jadi Microsoft-lah yang harus membawa Windows ke abad ini
Terakhir kali saya harus menangani file CSV di bash, saya mengubahnya dulu secara internal menjadi RS dan FS untuk diproses
Sebagai pengganti strncpy, di kode kernel Linux disarankan memakai strscpy() untuk tujuan berterminasi NUL, strscpy_pad() untuk tujuan berterminasi NUL yang butuh padding 0, strtomem_pad() untuk field lebar tetap yang tidak berterminasi NUL, memcpy_and_pad() untuk penyalinan berbatas dengan padding eksplisit, dan memcpy() untuk penyalinan memori dengan panjang yang sudah diketahui
Ini terdengar seperti mimpi buruk, dan saya tidak tahu apakah memang harus serumit ini
Saat membaca kode, saya rasa lebih baik kalau niat pengembang bisa langsung terlihat jelas hanya dari fungsi yang dipilih
Pekerjaan repetitif yang membosankan seperti inilah tempat pekerjaan nyata rekayasa sistem benar-benar terjadi
Proyek infrastruktur besar seperti ini, yang membuat kernel Linux lebih andal sambil tetap menjaganya bisa dipakai di dunia nyata sepanjang seluruh proses, bergerak dalam skala puluhan tahun, bukan hitungan bulan
Tapi saya tidak yakin apakah dengan kecepatan seperti itu masih bisa dihasilkan kemajuan jangka panjang yang benar-benar berarti. Ini bukan keluhan, lebih seperti paradoks infrastruktur inti
Ini pekerjaan yang luar biasa dan bikin rendah hati. Mengejutkan melihat begitu banyak orang ikut berkontribusi
“Fitur baru yang keren” mudah mendapat pengakuan, tetapi pada sesuatu yang mendasar seperti kernel, menghapus fitur buruk justru bisa jadi lebih penting
Jika 50 tahun lagi orang-orang lupa cara membaca source code, sementara ampas Claude/Codex diam-diam menumpuk dan membakar sebagian besar energi bumi, pekerjaan seperti ini mungkin akan tersisa sebagai legenda dari “era pendirian”
Sekaligus satu-satunya orang yang tahu apa itu Unix epoch
Saya rasa string berakhiran 0 adalah kesalahan terbesar dalam sejarah komputasi. String gaya Pascal jauh lebih aman
Itu tetap pointer ke array karakter yang diakhiri 0, tetapi tepat sebelum byte pertama yang ditunjuk pointer ada field panjang. Dengan asumsi tidak ada NUL tertanam, ini juga kompatibel dengan string C, dan fungsi bertipe BSTR bisa memanfaatkan nilai panjangnya
Pada suatu masa, bahkan 16-bit mungkin terasa terlalu berlebihan, sedangkan sekarang 32-bit bisa terasa terlalu kecil. C yang disebut bahasa dengan “strong typing” justru cukup longgar di bagian yang sebenarnya penting
Saya sudah lebih dari 30 tahun tidak menulis kode Pascal, tetapi samar-samar ingat bahwa bahkan dulu pun sistem string-nya terasa terlalu merepotkan untuk dipakai
Terlalu banyak rasa sakit dan kerja sia-sia yang muncul hanya karena tidak ada tipe data string
strncpyjuga memakai tipe dan fungsi itu, bukan?Saya penasaran apa yang membuat penulisan ulang penggunaan strncpy begitu sulit sampai butuh 6 tahun
Apakah karena cakupan pemakaiannya memang seluas itu, atau ini pekerjaan jangka panjang yang hanya diganti saat kebetulan menyentuh file yang sama, atau ada kesulitan lain?
Saya pernah menangani kode di aplikasi Win32 yang memakai string berpadding spasi. String tujuan dipadding dengan spasi, tetapi byte terakhirnya tetap null terminator
Untuk operasi seperti panjang dan penyalinan, harus memakai versi khusus dari fungsi string. Saya tidak tahu alasannya, tetapi codebase-nya sangat tua, jadi mungkin berasal dari perilaku struct Pascal