Das Problem ist hier:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Wenn die Zeichenfolge größer als die Länge des Zielpuffers ist, kopiert strncpy sie weiterhin. Sie verwenden die Anzahl der Zeichen der Zeichenfolge als die zu kopierende Anzahl anstelle der Größe des Puffers. Der richtige Weg, dies zu tun, ist wie folgt:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Dadurch wird die Menge der kopierten Daten auf die tatsächliche Größe des Puffers minus eins für das Null-Abschlusszeichen begrenzt. Dann setzen wir das letzte Byte im Puffer als zusätzlichen Schutz auf das Nullzeichen. Der Grund dafür ist, dass strncpy bis zu n Bytes kopiert, einschließlich der abschließenden Null, wenn strlen (str) <len - 1. Wenn nicht, wird die Null nicht kopiert und Sie haben ein Absturzszenario, da Ihr Puffer jetzt nicht abgeschlossen ist Zeichenfolge.
Hoffe das hilft.
BEARBEITEN: Nach weiterer Prüfung und Eingabe durch andere folgt eine mögliche Codierung für die Funktion:
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);
}
Da wir die Länge der Zeichenfolge bereits kennen, können wir memcpy verwenden, um die Zeichenfolge von der Position, auf die str verweist, in den Puffer zu kopieren. Beachten Sie, dass auf der Handbuchseite für strlen (3) (auf einem FreeBSD 9.3-System) Folgendes angegeben ist:
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.
Was ich so interpretiere, dass die Länge der Zeichenfolge nicht die Null enthält. Aus diesem Grund kopiere ich len + 1 Bytes, um die Null einzuschließen, und der Test prüft, ob die Länge <Größe des Puffers - 2 ist. Minus eins, da der Puffer an Position 0 beginnt, und minus eins, um sicherzustellen, dass Platz vorhanden ist für die Null.
BEARBEITEN: Es stellt sich heraus, dass die Größe von etwas mit 1 beginnt, während der Zugriff mit 0 beginnt. Daher war die -2 vorher falsch, da sie einen Fehler für alles> 98 Bytes zurückgeben würde, aber> 99 Bytes sein sollte.
BEARBEITEN: Obwohl die Antwort auf eine vorzeichenlose Kurzform im Allgemeinen korrekt ist, da die maximal darstellbare Länge 65.535 Zeichen beträgt, spielt dies keine Rolle, da der Wert umbrochen wird, wenn die Zeichenfolge länger ist. Es ist, als würde man 75.231 (das ist 0x000125DF) nehmen und die oberen 16 Bits maskieren, was 9695 (0x000025DF) ergibt. Das einzige Problem, das ich dabei sehe, sind die ersten 100 Zeichen nach 65.535, da die Längenprüfung das Kopieren zulässt, aber in allen Fällen nur bis zu den ersten 100 Zeichen der Zeichenfolge kopiert und die Zeichenfolge mit Null beendet wird . Selbst mit dem Wraparound-Problem wird der Puffer immer noch nicht überlaufen.
Dies kann an sich ein Sicherheitsrisiko darstellen oder nicht, abhängig vom Inhalt der Zeichenfolge und dem, wofür Sie sie verwenden. Wenn es sich nur um geraden Text handelt, der von Menschen gelesen werden kann, gibt es im Allgemeinen kein Problem. Sie erhalten nur eine abgeschnittene Zeichenfolge. Wenn es sich jedoch um eine URL oder sogar eine SQL-Befehlssequenz handelt, liegt möglicherweise ein Problem vor.