Problem jest tutaj:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Jeśli łańcuch jest większy niż długość bufora docelowego, strncpy nadal go kopiuje. Liczbę znaków łańcucha opierasz na liczbie do skopiowania, a nie na rozmiarze bufora. Prawidłowy sposób na zrobienie tego jest następujący:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
To powoduje ograniczenie ilości danych kopiowanych do rzeczywistego rozmiaru bufora minus jeden dla znaku kończącego wartość null. Następnie ustawiamy ostatni bajt w buforze na znak null jako dodatkowe zabezpieczenie. Powodem tego jest to, że strncpy skopiuje do n bajtów, w tym kończący null, jeśli strlen (str) <len - 1. Jeśli nie, to wartość null nie jest kopiowana i masz scenariusz awarii, ponieważ teraz twój bufor ma niezakończony strunowy.
Mam nadzieję że to pomoże.
EDYCJA: Po dalszej analizie i wprowadzeniu informacji przez innych, możliwe kodowanie funkcji jest następujące:
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);
}
Ponieważ znamy już długość ciągu, możemy użyć memcpy do skopiowania ciągu z lokalizacji, do której odwołuje się str, do bufora. Zauważ, że na stronie podręcznika dla strlen (3) (w systemie FreeBSD 9.3) podano, co następuje:
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.
Co interpretuję jako, że długość łańcucha nie obejmuje wartości null. Dlatego kopiuję len + 1 bajtów, aby uwzględnić wartość null, a test sprawdza, czy długość <rozmiar bufora - 2. Minus jeden, ponieważ bufor zaczyna się na pozycji 0, a minus kolejny, aby upewnić się, że jest miejsce dla null.
EDYCJA: Okazuje się, że rozmiar czegoś zaczyna się od 1, a dostęp zaczyna się od 0, więc -2 przedtem było niepoprawne, ponieważ zwróciłoby błąd dla czegokolwiek> 98 bajtów, ale powinno być> 99 bajtów.
EDYCJA: Chociaż odpowiedź na temat skrótu bez znaku jest ogólnie poprawna, ponieważ maksymalna długość, którą można przedstawić, to 65 535 znaków, nie ma to większego znaczenia, ponieważ jeśli ciąg jest dłuższy, wartość zawinie się. To tak, jakby wziąć 75,231 (co jest 0x000125DF) i zamaskować górne 16 bitów, dając 9695 (0x000025DF). Jedynym problemem, jaki widzę w tym przypadku, jest pierwsze 100 znaków po 65 535, ponieważ sprawdzenie długości pozwoli na kopiowanie, ale we wszystkich przypadkach skopiuje tylko do pierwszych 100 znaków ciągu i zeruje ciąg . Więc nawet w przypadku problemu zawijania, bufor nadal nie zostanie przepełniony.
Może to samo w sobie stanowić zagrożenie bezpieczeństwa, w zależności od zawartości ciągu i tego, do czego go używasz. Jeśli jest to zwykły tekst, który jest czytelny dla człowieka, to generalnie nie ma problemu. Otrzymujesz po prostu obcięty ciąg. Jeśli jednak jest to adres URL lub nawet sekwencja poleceń SQL, możesz mieć problem.