Masalahnya ada di sini:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Jika string lebih besar dari panjang buffer target, strncpy akan tetap menyalinnya. Anda mendasarkan jumlah karakter string sebagai angka yang akan disalin, bukan ukuran buffer. Cara yang benar untuk melakukan ini adalah sebagai berikut:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Apa yang dilakukan adalah membatasi jumlah data yang disalin ke ukuran aktual buffer dikurangi satu untuk karakter terminasi nol. Kemudian kita mengatur byte terakhir dalam buffer ke karakter nol sebagai perlindungan tambahan. Alasan untuk ini adalah karena strncpy akan menyalin hingga n byte, termasuk null terminating, jika strlen (str) <len - 1. Jika tidak, maka null tidak disalin dan Anda memiliki skenario macet karena sekarang buffer Anda memiliki underminated tali.
Semoga ini membantu.
EDIT: Setelah pemeriksaan lebih lanjut dan masukan dari orang lain, kemungkinan pengkodean untuk fungsi ini adalah sebagai berikut:
int func (char *str)
{
char buffer[100];
unsigned short size = sizeof(buffer);
unsigned short len = strlen(str);
if (len > size - 1) return(-1);
memcpy(buffer, str, len + 1);
buffer[size - 1] = '\0';
return(0);
}
Karena kita sudah mengetahui panjang string, kita bisa menggunakan memcpy untuk menyalin string dari lokasi yang dirujuk oleh str ke buffer. Perhatikan bahwa per halaman manual untuk strlen (3) (pada sistem FreeBSD 9.3), berikut ini dinyatakan:
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
Yang saya menafsirkan bahwa panjang string tidak termasuk nol. Itu sebabnya saya menyalin len +1 byte untuk memasukkan nol, dan tes memeriksa untuk memastikan bahwa panjang <ukuran buffer - 2. Minus satu karena buffer dimulai pada posisi 0, dan minus satu lagi untuk memastikan ada ruang untuk nol.
EDIT: Ternyata, ukuran sesuatu dimulai dengan 1 sementara akses dimulai dengan 0, jadi -2 sebelumnya salah karena akan mengembalikan kesalahan untuk apa pun> 98 byte tetapi seharusnya> 99 byte.
EDIT: Meskipun jawaban tentang unsigned short umumnya benar karena panjang maksimum yang dapat diwakili adalah 65.535 karakter, itu tidak terlalu penting karena jika string lebih panjang dari itu, nilainya akan membungkus. Ini seperti mengambil 75.231 (yang merupakan 0x000125DF) dan menutupi 16 bit teratas memberi Anda 9695 (0x000025DD). Satu-satunya masalah yang saya lihat dengan ini adalah 100 karakter pertama melewati 65.535 karena pemeriksaan panjang akan memperbolehkan penyalinan, tetapi hanya akan menyalin hingga 100 karakter pertama dari string dalam semua kasus dan null mengakhiri string . Begitu pun dengan masalah sampulnya, buffer masih tidak akan meluap.
Ini mungkin atau tidak dengan sendirinya menimbulkan risiko keamanan tergantung pada konten string dan untuk apa Anda menggunakannya. Jika hanya teks lurus yang dapat dibaca manusia, maka umumnya tidak ada masalah. Anda hanya mendapatkan string terpotong. Namun, jika itu sesuatu seperti URL atau bahkan urutan perintah SQL, Anda bisa memiliki masalah.