it-swarm.com.de

Warum sollten Sie strncpy anstelle von strcpy verwenden?

Edit: Ich habe die Quelle für das Beispiel hinzugefügt.

Ich bin auf dieses Beispiel gestoßen:

char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;

/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);

/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );

Was hat diese Ausgabe produziert:

ziel ist ursprünglich = "abcdefg" 
 Nach strcpy wird "123456789" 

 Ziel1 ist ursprünglich = "Abcdefg" 
 Nach strncpy wird Ziel1 "12345fg" 

Deshalb wundere ich mich, warum jemand diesen Effekt haben möchte. Es sieht so aus, als wäre es verwirrend. Dieses Programm lässt mich denken, dass man mit Tom Bro763 grundsätzlich den Namen einer Person (zB Tom Brokaw) überschreiben könnte. 

Was sind die Vorteile vonstrncpy()überstrcpy()?

70
Kredns

strncpy bekämpft den Pufferüberlauf, indem Sie eine Länge angeben. strcpy hängt von einem nachlaufenden \0 ab, der möglicherweise nicht immer auftritt.

Zweitens: Warum Sie sich entschieden haben, nur 5 Zeichen in einer 7-Zeichen-Zeichenfolge zu kopieren, ist mir unklar, erzeugt aber ein erwartetes Verhalten. Es werden nur die ersten n-Zeichen kopiert, wobei n das dritte Argument ist.

Die n-Funktionen werden alle als defensive Codierung gegen Pufferüberläufe verwendet. Bitte verwenden Sie diese anstelle von älteren Funktionen wie strcpy.

85
Eric

Die Funktion strncpy() wurde mit einem besonderen Problem entwickelt: Manipulation von Zeichenfolgen, die wie Original-UNIX-Verzeichniseinträge gespeichert wurden. Diese verwendeten ein Array mit fester Größe und ein Nul-Terminator wurde nur verwendet, wenn der Dateiname kürzer war als das Array.

Das ist, was hinter den beiden Kuriositäten von strncpy() steckt:

  • Wenn das Ziel vollständig gefüllt ist, wird dem Ziel kein Nul-Terminator zugewiesen. und
  • Es füllt das Ziel immer vollständig aus, wenn nötig mit Nuls.

Für eine "sicherere strcpy()" ist es besser, strncat() wie folgt zu verwenden:

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

Dadurch wird das Ergebnis immer abgebrochen und nicht mehr als nötig kopiert.

157
caf

Ich kenne zwar die Absicht hinter strncpy, ist aber keine wirklich gute Funktion. Beides vermeiden. Raymond Chen erklärt .

Persönlich ist meine Schlussfolgerung einfach, strncpy und alle seine Freunde zu vermeiden, wenn Sie mit nullterminierten Strings arbeiten. Trotz des "str" ​​im Namen erzeugen diese Funktionen keine nullterminierten Zeichenfolgen. Sie konvertieren eine nullterminierte Zeichenfolge in einen Rohzeichenpuffer. Sie zu verwenden, wenn eine mit Null abgeschlossene Zeichenfolge als zweiter Puffer erwartet wird, ist schlicht falsch. Nicht nur, wenn die Quelle zu lang ist, erhalten Sie keine ordnungsgemäße Nullauslösung, und wenn die Quelle zu kurz ist, erhalten Sie unnötige Nullauffüllung. 

Siehe auch Warum ist strncpy unsicher?

30
Sinan Ünür

strncpy ist NICHT sicherer als strcpy, es tauscht nur eine Art von Fehlern mit einer anderen. Wenn Sie in C mit C-Strings arbeiten, müssen Sie die Größe Ihrer Puffer kennen. strncpy war für die von anderen genannten Verzeichnisse berechtigt, aber ansonsten sollten Sie es niemals verwenden:

  • wenn Sie die Länge Ihrer Zeichenfolge und Ihres Puffers kennen, warum sollten Sie strncpy verwenden? Es ist bestenfalls eine Verschwendung von Rechenleistung (Hinzufügen von nutzlosen 0)
  • wenn Sie die Längen nicht kennen, besteht die Gefahr, dass Sie die Zeichenfolgen stumm abschneiden. Dies ist nicht viel besser als ein Pufferüberlauf
26

Was Sie suchen, ist die Funktion strlcpy(), die den String immer mit 0 abschließt und den Puffer initialisiert. Es kann auch Überläufe erkennen. Das einzige Problem ist, dass es nicht (wirklich) portabel ist und nur auf einigen Systemen (BSD, Solaris) vorhanden ist. Das Problem bei dieser Funktion ist, dass eine weitere Dose Würmer geöffnet wird, wie aus den Diskussionen auf ersichtlich ist http://en.wikipedia.org/wiki/Strlcpy

Meine persönliche Meinung ist, dass es wesentlich nützlicher ist als strncpy() und strcpy(). Es hat eine bessere Leistung und ist ein guter Begleiter von snprintf(). Für Plattformen, die es nicht haben, ist es relativ einfach zu implementieren .. (. Für die Entwicklungsphase einer Anwendung ersetze ich diese beiden Funktionen (snprintf() und strlcpy()) durch eine Trapping-Version, die das Programm bei Pufferüberläufen oder -kürzungen brutal abbricht Dies ermöglicht es, die schlimmsten Täter schnell zu fassen, besonders wenn Sie an einer Codebasis von jemand anderem arbeiten.

BEARBEITEN: strlcpy() kann leicht implementiert werden:

size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
  size_t len = strlen(src);
  if(dstsize) {
    size_t bl = (len < dstsize-1 ? len : dstsize-1);
    ((char*)memcpy(dst, src, bl))[bl] = 0;
  }
  return len;
}
20

Die Funktion strncpy() ist die sicherere: Sie müssen die maximale Länge übergeben, die der Zielpuffer annehmen kann. Andernfalls kann es vorkommen, dass der Quellstring nicht korrekt 0 beendet wird. In diesem Fall könnte die Funktion strcpy() mehr Zeichen in das Ziel schreiben, wodurch alles beschädigt wird, was sich nach dem Zielpuffer im Speicher befindet. Dies ist das Pufferüberlaufproblem, das bei vielen Exploits verwendet wird

Auch für POSIX-API-Funktionen wie read(), die die abschließende 0 nicht in den Puffer einfügen, sondern die Anzahl der gelesenen Bytes zurückgeben, werden Sie entweder die 0 manuell eingeben oder sie mit strncpy() kopieren.

In Ihrem Beispielcode ist index eigentlich kein Index, sondern eine count. Sie gibt an, wie viele Zeichen höchstens von Quelle zu Ziel kopiert werden sollen. Wenn sich unter den ersten n Bytes der Quelle kein Null-Byte befindet, wird die im Ziel platzierte Zeichenfolge nicht mit Null abgeschlossen

3
CsTamas

strncpy füllt das Ziel mit '\ 0' für die Quellgröße auf, obwohl das Ziel kleiner ist ...

manpage:

Wenn die Länge von src kleiner als n ist, füllt strncpy () den Rest von .__ auf. dest mit null Bytes.

und nicht nur der rest ... auch danach bis n zeichen erreicht. Und so entsteht ein Überlauf ... (siehe Manpage Implementierung)

1
Jeronimo

Das hängt von unserer Anforderung ab ... Für Windows-Benutzer

Wir verwenden strncpy immer dann, wenn wir nicht die gesamte Zeichenfolge oder nur n Zeichen kopieren möchten. Strcpy kopiert jedoch die gesamte Zeichenfolge einschließlich des abschließenden Nullzeichens.

Diese Links helfen Ihnen, mehr über strcpy und strncpy Zu erfahren und wo wir sie verwenden können.

über strcpy

über strncpy

0
Prakash

Dies kann in vielen anderen Szenarien verwendet werden, in denen Sie nur einen Teil Ihrer ursprünglichen Zeichenfolge an das Ziel kopieren müssen. Mit strncpy () können Sie einen begrenzten Teil der Originalzeichenfolge im Gegensatz zu strcpy () kopieren. Ich sehe, dass der von Ihnen eingegebene Code aus publib.boulder.ibm.com stammt.

0
ARV