Frage

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

Ich stieß auf Dieses Beispiel:

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 );

Die diese Ausgabe erzeugte:

destination is originally = 'abcdefg'
After strcpy, destination becomes '123456789'

destination1 is originally = 'abcdefg'
After strncpy, destination1 becomes '12345fg'

Was mich frage, warum jemand diesen Effekt wollen würde. Es sieht so aus, als wäre es verwirrend. Dieses Programm lässt mich denken, Sie könnten im Grunde genommen den Namen eines Menschen (z. B. Tom Brokaw) mit Tom Bro763 kopieren.

Was sind die Vorteile der Verwendung strncpy() Über strcpy()?

War es hilfreich?

Lösung

strncpy Bekämpft den Pufferüberlauf, indem Sie eine Länge einlegen. strcpy hängt von einem Nachfolger ab \0, was nicht immer auftreten kann.

Zweitens, warum Sie sich entschieden haben, nur 5 Zeichen auf 7 Charakter -Zeichenfolge zu kopieren, ist mir ein Rätsel, aber es erzeugt das erwartete Verhalten. Es kopiert nur über den ersten n Charaktere, wo n ist das dritte Argument.

Das n Funktionen werden alle als defensive Codierung gegen Pufferüberläufe verwendet. Bitte verwenden Sie sie anstelle älterer Funktionen, wie z. strcpy.

Andere Tipps

Das strncpy() Die Funktion wurde unter Berücksichtigung eines ganz besonderen Problems entworfen: Manipulation von Zeichenfolgen, die in der Art von ursprünglichen Unix -Verzeichniseinträgen gespeichert wurden. Diese verwendeten ein Array mit fester Größe, und ein Nul-Terminator wurde nur verwendet, wenn der Dateiname kürzer als das Array war.

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

  • Es ist kein Nul-Terminator auf das Ziel, wenn er vollständig gefüllt ist. und
  • Es füllt das Ziel immer vollständig mit Nuls, falls erforderlich.

Für ein "sicherer strcpy()", Sie sind besser dran. strncat() Like SO:

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

Das wird das Ergebnis immer mit NUL beenden und wird nicht mehr als nötig kopieren.

Während ich die Absicht dahinter kenne strncpy, Es ist nicht wirklich eine gute Funktion. Vermeiden Sie beides. Raymond Chen erklärt.

Persönlich ist meine Schlussfolgerung einfach, einfach zu vermeiden strncpy Und alle seine Freunde, wenn Sie sich mit null-terminierten Saiten zu beschäftigen. Trotz des "STR" im Namen erzeugen diese Funktionen keine null-terminierten Saiten. Sie konvertieren eine null-terminierte Schnur in einen rohen Charakterpuffer. Die Verwendung einer Null-terminierten Zeichenfolge wird erwartet, da der zweite Puffer einfach falsch ist. Sie erhalten nicht nur die ordnungsgemäße Null -Beendigung, wenn die Quelle zu lang ist, sondern wenn die Quelle kurz ist, erhalten Sie unnötige Nullpolsterung.

Siehe auch Warum ist Strncpy unsicher?

STRNCPY ist nicht sicherer als Strcpy, es handelt nur mit einer anderen Art von Fehler. Bei C -Saiten müssen Sie in C wissen, wie groß Sie die Größe Ihrer Puffer haben, es gibt keine Möglichkeit. STRNCPY war für das von anderen erwähnte Verzeichnissache gerechtfertigt, aber ansonsten sollten Sie es niemals verwenden:

  • Wenn Sie die Länge Ihrer Zeichenfolge und Ihres Puffers kennen, warum dann mit STRNCPY? Es ist bestenfalls eine Verschwendung von Rechenleistung (fügen Sie nutzlos 0 hinzu)
  • Wenn Sie die Längen nicht kennen, riskieren Sie stillschweigend Ihre Saiten, was nicht viel besser ist als ein Pufferüberlauf

Was Sie suchen, ist die Funktion strlcpy() Was immer die Zeichenfolge mit 0 beendet und den Puffer initialisiert. Es ist auch in der Lage, Überläufe zu erkennen. Es ist nur ein Problem, es ist nicht (wirklich) tragbar und ist nur in einigen Systemen (BSD, Solaris) vorhanden. Das Problem mit dieser Funktion ist, dass es eine andere Dose Würmer öffnet, wie die Diskussionen über gesehen werden könnenhttp://en.wikipedia.org/wiki/strlcpy

Meine persönliche Meinung ist, dass es weitaus nützlicher ist als strncpy() und strcpy(). Es hat eine bessere Leistung und ist ein guter Begleiter für 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()) mit einer Fallenversion, die das Programm auf Pufferüberläufen oder Kürzungen brutal abbricht. Dies ermöglicht es, die schlimmsten Straftäter schnell zu fangen. Vor allem, 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;
}

Das strncpy() Funktion ist die sicherere: Sie müssen die maximale Länge übergeben, die der Zielpuffer akzeptieren kann. Andern strcpy() Die Funktion könnte mehr Zeichen an das Ziel schreiben und alles, was nach dem Zielpuffer im Speicher liegt, verfälscht. Dies ist das Puffer-Overrun-Problem, das in vielen Exploits verwendet wird

Auch für POSIX -API -Funktionen wie read() Dies stellt die Beendigung 0 nicht in den Puffer, sondern gibt die Anzahl der gelesenen Bytes zurück. Sie werden die 0 entweder manuell einstellen oder kopieren strncpy().

In Ihrem Beispielcode, index ist eigentlich kein Index, sondern a count - Es zeigt, wie viele Charaktere maximal So kopieren Sie von der Quelle zum Ziel. Wenn unter den ersten N -Bytes der Quelle kein Null -Byte vorhanden ist, wird die am Ziel festgelegte Zeichenfolge nicht null gekündigt

strncpy fills the destination up with '\0' for the size of source, eventhough the size of the destination is smaller....

manpage:

If the length of src is less than n, strncpy() pads the remainder of dest with null bytes.

and not only the remainder...also after this until n characters is reached. And thus you get an overflow... (see the man page implementation)

This may be used in many other scenarios, where you need to copy only a portion of your original string to the destination. Using strncpy() you can copy a limited portion of the original string as opposed by strcpy(). I see the code you have put up comes from publib.boulder.ibm.com.

That depends on our requirement. For windows users

We use strncpy whenever we don't want to copy entire string or we want to copy only n number of characters. But strcpy copies the entire string including terminating null character.

These links will help you more to know about strcpy and strncpy and where we can use.

about strcpy

about strncpy

the strncpy is a safer version of strcpy as a matter of fact you should never use strcpy because its potential buffer overflow vulnerability which makes you system vulnerable to all sort of attacks

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top