11 poin oleh GN⁺ 2026-01-01 | 5 komentar | Bagikan ke WhatsApp
  • Setelah sebelumnya menghapus strncpy() dari proyek, cURL kini melarang strcpy() sepenuhnya dari codebase
  • API strcpy() memang sederhana, tetapi ada risiko validasi ukuran buffer terpisah sehingga tidak aman untuk pemeliharaan jangka panjang
  • Sebagai gantinya, diperkenalkan fungsi baru bernama curlx_strcopy() yang menerima ukuran buffer tujuan dan panjang string sebagai argumen, lalu memeriksa apakah penyalinan aman sebelum dijalankan
  • Fungsi ini secara internal menggunakan memcpy() dan menjamin penanganan karakter null terminator
  • Perubahan ini dapat meningkatkan keamanan dan konsistensi kode, sekaligus mengurangi masalah AI yang menghasilkan laporan kerentanan yang keliru

Latar belakang penghapusan strcpy

  • cURL sebelumnya telah menghapus seluruh pemanggilan strncpy(), sambil menyoroti masalah API yang tidak intuitif, kegagalan menjamin null terminator, dan 0 padding yang tidak perlu
    • Untuk kasus yang memerlukan penyalinan substring, pendekatannya diubah menjadi menggunakan memcpy() dan menangani null terminator secara manual
  • API strcpy() memang sederhana, tetapi karena tidak menyatakan ukuran buffer secara eksplisit, ada risiko kode validasi dan pemanggilan penyalinan terpisah saat pemeliharaan
    • Jika kode dimodifikasi selama puluhan tahun oleh banyak pengembang, ada kemungkinan validasi ukuran buffer menjadi tidak efektif

Pengenalan fungsi penyalin string baru

  • Untuk mencegah risiko tersebut, diperkenalkan fungsi pengganti bernama curlx_strcopy()
    • Argumennya adalah buffer tujuan, ukuran buffer, buffer sumber, dan panjang string sumber
    • Penyalinan dengan memcpy() hanya dilakukan jika penyalinan dan null termination sama-sama memungkinkan
    • Jika gagal, buffer tujuan diinisialisasi sebagai string kosong
  • Fungsi ini memang membutuhkan lebih banyak argumen dan lebih banyak kode dibanding strcpy(), tetapi mengaitkan validasi buffer dengan proses penyalinan secara erat untuk menjamin keamanan
  • Penggunaan strcpy() kini dilarang sepenuhnya di codebase cURL, sama seperti strncpy() yang telah lebih dulu dihapus

Detail implementasi

  • Contoh definisi fungsi adalah sebagai berikut
    void curlx_strcopy(char *dest, size_t dsize, const char *src, size_t slen)
    {
      DEBUGASSERT(slen < dsize);
      if(slen < dsize) {
        memcpy(dest, src, slen);
        dest[slen] = 0;
      }
      else if(dsize)
        dest[0] = 0;
    }
    
  • DEBUGASSERT dipakai untuk mendeteksi kesalahan lebih awal selama pengembangan, dan dirancang agar selalu berhasil di lingkungan rilis aktual
  • Seperti strcpy, fungsi ini tidak memiliki nilai balik, dan memakai pendekatan menangkap kesalahan pada tahap pengujian dan fuzzing

Reaksi komunitas

  • Sebagian pengembang menilai ini mirip dengan strcpy_s() (C11 Annex K), tetapi cURL masih menggunakan standar C89
  • Ada juga masukan lain seperti perlunya nilai balik atau perbaikan penanganan saat buffer gagal
  • Menanggapi hal itu, pihak cURL menjelaskan bahwa “karena fungsi ini dirancang agar selalu berhasil, nilai balik tidak diperlukan”

Efek tambahan terkait AI

  • Perubahan ini juga dapat mencegah chatbot AI salah mendeteksi penggunaan strcpy di kode cURL lalu mengklaimnya ‘rentan’
  • Namun, penulis tetap menyebut bahwa “AI masih mungkin menghasilkan laporan palsu lainnya”, sambil menyinggung batasan analisis kode berbasis AI

5 komentar

 
ahwjdekf 2026-01-02

Benar, yang tepat adalah menggunakan snprintf alih-alih strcpy. Kalau ada strcpy di dalam kode, kita perlu mencari tahu alamat pengembang yang membuatnya.

 
winmain 2026-01-02

Itu adalah cara yang dulu saya kerjakan sebagai kode debug saat bekerja di perusahaan game 25 tahun lalu, dan tentu bukan cuma strcpy saja. Saat rilis, itu kembali dilonggarkan demi peningkatan kecepatan lalu dipakai dalam layanan. Sebenarnya, di bidang game benturan memori adalah hal yang paling sensitif, jadi pengerjaannya juga dilakukan dengan sangat hati-hati dan penuh kewaspadaan; kami bahkan membuat dan memakai debugger memori sendiri. Tapi ketika melihatnya sekarang, ternyata kami waktu itu sedang membuat garbage collection. Kenangan yang samar dan manis.

 
secwind 2026-01-02

Error C4996 'strcpy': Fungsi atau variabel ini mungkin tidak aman. Pertimbangkan untuk menggunakan strcpy_s sebagai gantinya. Untuk menonaktifkan deprecation, gunakan _CRT_SECURE_NO_WARNINGS. Lihat bantuan online untuk detailnya.

 
GN⁺ 2026-01-01
Komentar Hacker News
  • strcpy() tidak baik bukan hanya dari sisi keamanan, tetapi juga dari sisi performa
    Dulu orang menganggap strcpy() efisien saat panjang string tidak diketahui, tetapi pada praktiknya ia menyalin satu byte demi satu byte sehingga CPU harus melakukan prediksi cabang, dan ini tidak efisien

    • Sekarang saya berpikir kita sebaiknya sebisa mungkin meninggalkan string null-terminated itu sendiri
    • Belakangan ini saya belum pernah melihat strcpy memakai loop skalar. Saya penasaran apakah itu hanya terjadi di arsitektur ARM
  • Rutinitas string di C semuanya terasa tidak berguna karena masing-masing punya keterbatasan besar
    Karena itu saya merasa benar-benar dibutuhkan pustaka yang, bersama pointer string, juga mencatat ukuran memori yang dialokasikan
    Sebagai contoh, pustaka bstring layak dijadikan referensi

    • strncpy dibuat untuk menyalin nama berkas dengan panjang tetap. Untuk penjelasan rinci, lihat jawaban StackOverflow ini
    • Tidak menyertakan informasi panjang pada string dulu dilakukan demi penghematan memori. Saat itu, satu byte pun sangat berharga
    • Fungsi-fungsi string di C menimbulkan masalah karena para perancang menambahkannya tanpa cukup mampu memprediksi akibatnya. Fakta bahwa array dipaksa dikonversi menjadi pointer saat menjadi argumen fungsi juga merupakan kesalahan desain yang mendasar
    • Book-keeping tambahan seperti ini dulu memang membebani, tetapi sekarang sudah berada pada tingkat yang sepenuhnya bisa ditanggung
    • strncpy pada awalnya adalah fungsi untuk menangani field string berlebar tetap. Misalnya, untuk mengisi field seperti char username[20] dengan padding NUL. Lihat dokumentasi terkait di manual string_copying.7
  • Agak aneh bahwa curlx_strcopy tidak mengembalikan status berhasil atau tidak
    Kita memang bisa memeriksa dest[0], tetapi ini sangat mudah memicu kesalahan dan tidak intuitif

    • Versi sebelumnya mengembalikan error, tetapi sekarang gagal secara diam-diam dan menetapkan string kosong. Ini aneh
    • Mungkin DEBUGASSERT(slen < dsize); dianggap sebagai tanda sukses jika lolos, tetapi pada build release assert bisa dihapus. Saya rasa kode error yang eksplisit lebih baik
    • Dengan desain seperti ini, saya melihat kemungkinan CVE akan muncul di masa depan
  • strncpy() pada awalnya bukan untuk string null-terminated, melainkan untuk field berpanjang tetap
    Masalahnya bermula ketika penganalisis statis merekomendasikan penggunaan strncpy sebagai pengganti strcpy. Padahal alternatif yang sebenarnya adalah snprintf atau strlcpy

    • strlcpy adalah fungsi keluarga BSD sehingga tidak ada di POSIX. Rekomendasi resminya adalah stpecpy, tetapi implementasi nyatanya hampir tidak ada. Lihat dokumentasi terkait
    • Alasan strncpy melakukan padding setelah null adalah untuk perbandingan yang efisien pada field nama berpanjang tetap seperti entri direktori. Hal itu juga dinyatakan dalam dokumen dasar standar ANSI C
  • API ini terasa seperti Annex-K. Ruang NUL dihitung dalam ukuran buffer tujuan, tetapi tidak dihitung dalam ukuran sumber
    Saya malah merasa lebih baik menulis memcpy secara langsung

  • Kalimat dalam artikel bahwa “strcpy adalah umpan yang membuat AI menghasilkan laporan kerentanan yang salah” sangat membekas

    • Pada kenyataannya, AI bukan sekadar menandai strcpy sebagai masalah, melainkan membuat pembuktian rumit yang mengandung kesalahan logika, sehingga maintainer harus bersusah payah memverifikasinya
    • Orang-orang yang mengirim laporan salah seperti ini entah tidak tahu bahwa AI bisa salah, atau memang tidak peduli. Toh tidak ada biaya atas laporan yang salah
    • Pada akhirnya, masalahnya adalah orang-orang yang memakai AI untuk penggunaan yang tidak tepat
  • Prinsip “periksa di dekat kode” itu bagus, tetapi menjadi rancu saat kita perlu memeriksa di awal siklus hidup data
    Akan bagus jika, seperti tipe Result di Rust, kita bisa membedakan lewat tipe bahwa ini adalah “data yang sudah tervalidasi”

    • Result hanya memuat sukses/gagal, dan tidak menjamin status tervalidasi. Sebagai gantinya, lebih baik punya tipe terpisah yang hanya bisa dibuat setelah melewati proses validasi. Inilah filosofi “** parse, don’t validate**”
    • Idealnya, validasi dilakukan bukan di dekat kode konsumen, melainkan sedini mungkin di batas sistem. Namun ini membutuhkan sistem tipe yang ekspresif
    • Dalam kasus seperti ini, membedakan tipe seperti String dan CharSequence di Java juga bisa menjadi salah satu cara
  • Perbedaan off-by-one antara ukuran buffer dan panjang string adalah masalah kegunaan yang mengerikan. Sangat mungkin terus memicu kesalahan ke depannya

  • Fungsi penyalinan string yang baru diusulkan akan mengosongkan buffer tujuan dan mengembalikan void jika penyalinan tidak memungkinkan
    Tetapi saya rasa dalam kasus seperti ini, lebih baik diperlakukan sebagai error dan buffer tidak disentuh. Mengandalkannya hanya pada DEBUGASSERT terasa tidak aman

  • Selamat menyelesaikan proyeknya. C/C++ pun, jika diupayakan, bisa mendapatkan keamanan memori
    Namun di lingkungan mobile, ukuran font grafik terlalu kecil sehingga keterbacaannya menurun

    • Menghapus strcpy tidak otomatis membuat kode menjadi aman terhadap memori
    • Font grafik tampaknya dirancang untuk cetak. Untuk blog, ukurannya terlalu kecil
 
hiongun 2026-01-04

Beralih sepenuhnya ke bahasa C3 juga bagus. Ini adalah proyek yang mempertahankan sintaks bahasa C dengan perubahan seminimal mungkin sambil menambahkan fitur-fitur modern, jadi migrasinya juga mudah.