Il problema è qui:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Se la stringa è maggiore della lunghezza del buffer di destinazione, strncpy lo copierà comunque. Si sta basando il numero di caratteri della stringa come numero da copiare anziché la dimensione del buffer. Il modo corretto per farlo è il seguente:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Quello che fa è limitare la quantità di dati copiati alla dimensione effettiva del buffer meno uno per il carattere che termina null. Quindi impostiamo l'ultimo byte nel buffer sul carattere null come protezione aggiuntiva. La ragione di ciò è perché strncpy copierà fino a n byte, incluso il null di terminazione, se strlen (str) <len - 1. In caso contrario, il null non viene copiato e si ha uno scenario di crash perché ora il buffer ha un terminale non terminato corda.
Spero che questo ti aiuti.
EDIT: dopo ulteriori esami e input da altri, segue una possibile codifica per la funzione:
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);
}
Dato che conosciamo già la lunghezza della stringa, possiamo usare memcpy per copiare la stringa dalla posizione a cui fa riferimento str nel buffer. Nota che nella pagina del manuale di strlen (3) (su un sistema FreeBSD 9.3), è indicato quanto segue:
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.
Ciò che interpreto è che la lunghezza della stringa non include il null. Questo è il motivo per cui copio len + 1 byte per includere il valore null e il test verifica che la lunghezza <dimensione del buffer - 2. Meno uno perché il buffer inizia nella posizione 0 e meno un altro per assicurarsi che ci sia spazio per il null.
EDIT: Si scopre che la dimensione di qualcosa inizia con 1 mentre l'accesso inizia con 0, quindi -2 prima non era corretto perché avrebbe restituito un errore per qualcosa> 98 byte ma dovrebbe essere> 99 byte.
EDIT: Sebbene la risposta su un short senza segno sia generalmente corretta poiché la lunghezza massima che può essere rappresentata è di 65.535 caratteri, non importa davvero perché se la stringa è più lunga, il valore andrà a capo. È come prendere 75.231 (che è 0x000125DF) e mascherare i primi 16 bit che ti danno 9695 (0x000025DF). L'unico problema che vedo con questo è i primi 100 caratteri oltre 65.535 poiché il controllo di lunghezza consentirà la copia, ma copierà fino ai primi 100 caratteri della stringa in tutti i casi e termina null la stringa . Quindi, anche con il problema avvolgente, il buffer non verrà comunque traboccato.
Questo può di per sé o meno costituire un rischio per la sicurezza a seconda del contenuto della stringa e del motivo per cui la si sta utilizzando. Se è solo un testo semplice che è leggibile dall'uomo, in genere non ci sono problemi. Ottieni solo una stringa troncata. Tuttavia, se si tratta di qualcosa di simile a un URL o addirittura a una sequenza di comandi SQL, potresti avere un problema.