flawopen.com/Keamanan memori/strcpy vs strncpy
Apakah strncpy() lebih aman daripada strcpy()?
Field berukuran tetap seperti deretan slot berlabel: slot terakhir harus menyimpan penanda akhir jika kode berikutnya memperlakukan byte sebagai string C. strncpy() menulis paling banyak n byte dan hanya mencegah penulisan melewati tujuan jika n tidak melebihi kapasitas buffer sebenarnya. Jika sumber memenuhi batas tersebut, terminator null tidak ditambahkan. Fungsi string berikutnya dapat membaca melewati tujuan saat mencari penanda yang hilang.
char dst[16]; /* 1. Unbounded — classic overflow */ strcpy(dst, src); /* 2. Bounded, but may not terminate. If strlen(src) >= 16, dst has no '\0' and every later strlen/printf reads out of bounds. */ strncpy(dst, src, sizeof(dst)); /* 3. Off-by-one: room for 16 chars plus a terminator = 17 bytes, but dst only holds 16. */ strncpy(dst, src, sizeof(dst)); dst[sizeof(dst)] = '\0'; /* OOB! */
char dst[16]; /* Preferred: snprintf always null-terminates (when size > 0), and tells you about truncation. */ int n = snprintf(dst, sizeof(dst), "%s", src); if (n < 0 || (size_t)n >= sizeof(dst)) { /* truncated — handle it */ return ERR_TOO_LONG; } /* Or strlcpy where available — always terminates, returns the length it tried to create. */ if (strlcpy(dst, src, sizeof(dst)) >= sizeof(dst)) { return ERR_TOO_LONG; }
Tujuan awal strncpy
Perilaku ini bukan cacat: strncpy() dirancang untuk field karakter berukuran tetap yang diisi null, bukan sebagai penyalinan string C yang aman untuk semua kebutuhan. Jika string sumber lebih pendek dari n, fungsi mengisi tujuan dengan byte null hingga n - 1. Jika tidak ada byte null dalam n byte pertama sumber, fungsi menyalin tepat n byte dan tidak mengakhiri tujuan. Ini cocok untuk beberapa format field tetap, tetapi berbahaya jika hasilnya diberikan ke API yang mengharapkan string berterminator null.
Jika sumber lebih pendek daripada n, padding wajib menulis sampai seluruh lebar field. Pada buffer besar dan sumber pendek, ini dapat melakukan lebih banyak pekerjaan daripada fungsi yang berhenti di terminator.
Selalu periksa pemotongan
Mencegah overflow baru separuh pekerjaan. Pemotongan diam-diam juga berisiko: hostname, path, atau nilai otorisasi yang terpotong dapat berubah makna. snprintf mengembalikan panjang yang ingin ditulis; bandingkan dengan ukuran buffer. Salah membaca nilai ini sebagai jumlah byte yang benar-benar ditulis juga relevan pada Citrix Bleed.
Pertanyaan umum
Fungsi tersebut mengakhiri string dan memeriksa batas, tetapi portabilitasnya tidak merata: dukungan baik di Windows dan implementasi yang beragam di tempat lain. Untuk banyak platform, snprintf biasanya lebih tersedia.
Tidak. Fungsi ini berasal dari OpenBSD dan tersedia luas di BSD serta macOS; glibc versi baru juga menambahkannya. Periksa ketersediaannya pada target Anda.
Utamakan std::string dan std::string_view yang mengelola panjang. Gunakan fungsi C hanya pada batas API yang mensyaratkan buffer mentah.