Sorun burada:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Dize hedef arabelleğin uzunluğundan büyükse, strncpy yine de kopyalar. Dizenin karakter sayısını, arabellek boyutu yerine kopyalanacak sayı olarak dayandırıyorsunuz. Bunu yapmanın doğru yolu aşağıdaki gibidir:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Bunun yaptığı, boş sonlandırma karakteri için tampon eksi gerçek boyutuna kopyalanan veri miktarını sınırlamaktır. Sonra arabellekteki son baytı null karaktere ek bir koruma olarak ayarladık. Bunun nedeni, strrn (str) <len - 1 ise strncpy sonlandırma null değeri de dahil olmak üzere n bayta kadar kopyalayacaktır. Değilse, null kopyalanmaz ve çökme senaryosuna sahip olursunuz çünkü artık ara belleğinizde sonlanmamış dize.
Bu yardımcı olur umarım.
DÜZENLEME: Daha fazla inceleme ve diğer girdilerden sonra, işlev için olası bir kodlama aşağıdaki gibidir:
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);
}
Dizenin uzunluğunu zaten bildiğimizden, dizeyi str tarafından arabelleğe alınan konumdan kopyalamak için memcpy'yi kullanabiliriz. Strlen (3) için manuel sayfada (FreeBSD 9.3 sisteminde) aşağıdakilerin belirtildiğine dikkat edin:
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.
Hangi dize uzunluğu null içermediği için yorumlamak. Bu yüzden len + 1 baytları null değerini içerecek şekilde kopyalarım ve test, <tampon boyutu - 2'nin uzunluğundan emin olmak için kontrol eder. null için.
DÜZENLEME: Görünüyor ki, erişim 0 ile başlarken bir şeyin boyutu 1 ile başlar, bu nedenle önceki -2 yanlıştır çünkü 98 bayttan büyük bir şey için bir hata döndürür, ancak> 99 bayt olmalıdır.
EDIT: İmzasız bir kısa hakkında cevap genellikle temsil edilebilir maksimum uzunluğu 65,535 karakter olduğu için doğru olsa da, gerçekten önemli değil, çünkü dize bundan daha uzunsa, değer sarılır. Bu 75.231 (0x000125DF) almak ve size 9695 (0x000025DF) veren ilk 16 bitin maskelenmesi gibi. Bununla ilgili gördüğüm tek sorun, uzunluk kontrolü kopyalamaya izin vereceği için 65,535'i geçen ilk 100 karakterdir, ancak her durumda dizenin yalnızca ilk 100 karakterine kadar kopyalar ve null dizeyi sonlandırır . Bu nedenle, sarma sorunu olsa bile, arabellek yine de taşmaz.
Bu, dizenin içeriğine ve ne için kullandığınıza bağlı olarak kendi başına bir güvenlik riski oluşturabilir veya etmeyebilir. İnsan tarafından okunabilen düz metinse, genellikle sorun yoktur. Sadece kesik bir dize alıyorsunuz. Ancak, URL veya hatta bir SQL komut dizisi gibi bir şey varsa, bir sorununuz olabilir.