Erstens war strlcpy
es nie als sichere Version von gedacht strncpy
(und strncpy
war auch nie als sichere Version von gedacht strcpy
). Diese beiden Funktionen sind völlig unabhängig voneinander. strncpy
ist eine Funktion, die überhaupt keine Beziehung zu C-Strings (dh nullterminierten Strings) hat. Die Tatsache, dass der str...
Name das Präfix enthält, ist nur ein historischer Fehler. Die Geschichte und der Zweck von strncpy
ist bekannt und gut dokumentiert. Dies ist eine Funktion, die für die Arbeit mit sogenannten Zeichenfolgen mit fester Breite (nicht mit C-Zeichenfolgen) erstellt wurde, die in einigen historischen Versionen des Unix-Dateisystems verwendet werden. Einige Programmierer werden heute durch seinen Namen verwirrt und nehmen an, dass dies strncpy
irgendwie als C-String-Kopierfunktion mit begrenzter Länge dienen soll (ein "sicheres" Geschwister vonstrcpy
), was in Wirklichkeit völliger Unsinn ist und zu schlechter Programmierpraxis führt. Die C-Standardbibliothek in ihrer aktuellen Form hat keinerlei Funktion zum Kopieren von C-Strings mit begrenzter Länge. Hier strlcpy
passt es hinein. Dies ist in der strlcpy
Tat eine echte Kopierfunktion mit begrenzter Länge, die für die Arbeit mit C-Strings entwickelt wurde. strlcpy
macht alles richtig, was eine Kopierfunktion mit begrenzter Länge tun sollte. Die einzige Kritik, die man darauf richten kann, ist, dass es leider kein Standard ist.
Zweitens ist es strncat
in der Tat eine Funktion, die mit C-Strings arbeitet und eine Verkettung mit begrenzter Länge ausführt (es ist in der Tat ein "sicheres" Geschwister von strcat
). Um diese Funktion richtig zu verwenden, muss der Programmierer besondere Sorgfalt walten lassen, da der Größenparameter, den diese Funktion akzeptiert, nicht wirklich die Größe des Puffers ist, der das Ergebnis empfängt, sondern die Größe seines verbleibenden Teils (auch das Abschlusszeichen) wird implizit gezählt). Dies kann verwirrend sein, da der Programmierer, um diese Größe an die Größe des Puffers zu binden, daran denken muss, einige zusätzliche Berechnungen durchzuführen, die häufig zur Kritik des Puffers verwendet werden strncat
.strlcat
kümmert sich um diese Probleme und ändert die Schnittstelle so, dass keine zusätzlichen Berechnungen erforderlich sind (zumindest im aufrufenden Code). Die einzige Grundlage, auf der ich dies kritisieren kann, ist, dass die Funktion nicht Standard ist. Funktionen aus der strcat
Gruppe werden im professionellen Code aufgrund der eingeschränkten Verwendbarkeit der Idee der Rescan-basierten String-Verkettung nur selten verwendet.
Wie diese Funktionen zu Sicherheitsproblemen führen können ... können sie einfach nicht. Sie können nicht in größerem Maße zu Sicherheitsproblemen führen, als die C-Sprache selbst "zu Sicherheitsproblemen führen kann". Sie sehen, es gab eine ganze Weile ein starkes Gefühl, dass sich die C ++ - Sprache in Richtung einer seltsamen Java-Variante entwickeln muss. Dieses Gefühl wirkt sich manchmal auch auf den Bereich der C-Sprache aus, was zu einer eher ahnungslosen und erzwungenen Kritik an C-Sprachmerkmalen und den Merkmalen der C-Standardbibliothek führt. Ich vermute, dass wir uns auch in diesem Fall mit so etwas befassen könnten, obwohl ich sicherlich hoffe, dass die Dinge nicht wirklich so schlimm sind.
strlcpy
undstrlcat
würde eine Art Fehlerbedingung melden, wenn sie gegen die Größenbeschränkung des Zielpuffers stoßen würden. Obwohl Sie die zurückgegebene Länge überprüfen können, um dies zu testen, ist dies nicht offensichtlich. Aber ich denke, das ist eine kleine Kritik. Das Argument "Sie fördern die Verwendung von C-Strings und sind daher schlecht" ist albern.strcpy
über den Schwellenwert liegt und damit „unsicher“, und ihre bevorzugte String-Kopierfunktion (ob esstrlcpy
,strcpy_s
oder auchstrncpy
) unter dem Schwellenwert liegt und damit „sicher“.strlcpy/strlcat
. Man könnte das allgemeine Konzept der nullterminierten Zeichenfolge "nicht mögen", aber darum geht es bei der Frage nicht. Wenn Sie "viele Gründe kennen, die Sie nicht mögenstrlcpy/strlcat
", sollten Sie wahrscheinlich Ihre eigene Antwort schreiben, anstatt zu erwarten, dass ich die Gedanken eines anderen lesen kann.strlcpy/strlcat
. Obwohl ich glaube zu verstehen, worum es geht, lehne ich es persönlich ab, dies als "Sicherheitsprobleme" im Bereich der traditionellen C-Sprache, wie ich sie kenne, anzuerkennen. Das habe ich in meiner Antwort angegeben.Ulrichs Kritik basiert auf der Idee, dass eine vom Programm nicht erkannte Zeichenfolgenabschneidung durch falsche Logik zu Sicherheitsproblemen führen kann. Um sicher zu sein, müssen Sie daher auf Kürzungen prüfen. Um dies für eine Zeichenfolgenverkettung zu tun, müssen Sie eine Überprüfung in der folgenden Richtung durchführen:
if (destlen + sourcelen > dest_maxlen) { /* Bug out */ }
Nun
strlcat
tut effektiv diese Prüfung, wenn der Programmierer das Ergebnis zu überprüfen , erinnert sich - so Sie können es sicher verwenden:if (strlcat(dest, source, dest_bufferlen) >= dest_bufferlen) { /* Bug out */ }
Ulrichs Argument ist, dass Sie, da Sie
destlen
undsourcelen
um sie haben müssen (oder sie neu berechnen müssen, wasstrlcat
effektiv ist), genauso gut das effizientere verwendenmemcpy
können:if (destlen + sourcelen > dest_maxlen) { goto error_out; } memcpy(dest + destlen, source, sourcelen + 1); destlen += sourcelen;
(Im obigen Code
dest_maxlen
ist die maximale Länge der Zeichenfolge, in der gespeichert werden kanndest
- eine weniger als die Größe desdest
Puffers.dest_bufferlen
Ist die volle Größe derdest buffer
).quelle
memcpy
kann jede Art von Speicher sein und ich habe eine zusätzliche Dimension zu überprüfen, wenn ich versuche, den Code zu verstehen. Ich hatte eine Legacy-App zum Debuggen, bei der alles mit memcpy erledigt wurde. Es war eine echte PITA, die korrigiert werden musste. Nach dem Portieren auf eine dedizierte String-Funktion ist das Lesen viel einfacher (und schneller, da viele unnötigestrlen
Elemente entfernt werden könnten).memcpy()
ist dies ausreichend (und möglicherweise effizienter alsstrcpy()
).memcpy()
ist eine String-Operation - sie wird schließlich in deklariert<string.h>
.Wenn Leute sagen, "
strcpy()
ist gefährlich, verwenden Siestrncpy()
stattdessen" (oder ähnliche Aussagen überstrcat()
usw., aber ich werdestrcpy()
hier als meinen Fokus verwenden), bedeuten sie, dass es keine Grenzen beim Einchecken gibtstrcpy()
. Eine zu lange Zeichenfolge führt daher zu Pufferüberläufen. Sie sind richtig. Mitstrncpy()
in diesem Fall wird Pufferüberläufe zu verhindern.Ich denke,
strncpy()
das behebt wirklich keine Fehler: Es löst ein Problem, das von einem guten Programmierer leicht vermieden werden kann.Als C - Programmierer, Sie müssen die Zielgröße kennen , bevor Sie Zeichenfolgen zu kopieren versuchen. Dies ist auch die Annahme in
strncpy()
undstrlcpy()
's letzten Parametern: Sie geben ihnen diese Größe. Sie können auch die Quellgröße kennen, bevor Sie Zeichenfolgen kopieren. Wenn das Ziel nicht groß genug ist, rufen Sie nicht anstrcpy()
. Ordnen Sie den Puffer entweder neu zu oder tun Sie etwas anderes.Warum mag ich nicht
strncpy()
?strncpy()
ist in den meisten Fällen eine schlechte Lösung: Ihre Zeichenfolge wird ohne vorherige Ankündigung abgeschnitten. Ich würde lieber zusätzlichen Code schreiben, um dies selbst herauszufinden, und dann die Vorgehensweise ausführen, die ich ausführen möchte, anstatt eine Funktion entscheiden zu lassen mir über was zu tun ist.strncpy()
ist sehr ineffizient. Es schreibt in jedes Byte im Zielpuffer. Sie brauchen diese Tausenden'\0'
am Ende Ihres Ziels nicht.'\0'
wenn das Ziel nicht groß genug ist. Sie müssen dies also trotzdem selbst tun. Die Komplexität ist die Mühe nicht wert.Nun kommen wir zu
strlcpy()
. Die Änderungen vonstrncpy()
machen es besser, aber ich bin nicht sicher, ob das spezifische Verhalten vonstrl*
ihre Existenz rechtfertigt: Sie sind viel zu spezifisch. Sie müssen noch die Zielgröße kennen. Es ist effizienter alsstrncpy()
weil es nicht unbedingt in jedes Byte im Ziel schreibt. Aber es löst ein Problem, das gelöst werden kann, indem man :*((char *)mempcpy(dst, src, n)) = 0;
.Ich glaube nicht, dass jemand das sagt
strlcpy()
oderstrlcat()
zu Sicherheitsproblemen führen kann, was er (und ich) sagen, dass sie zu Fehlern führen können, zum Beispiel wenn Sie erwarten, dass die vollständige Zeichenfolge anstelle eines Teils davon geschrieben wird.Das Hauptproblem hierbei ist: Wie viele Bytes müssen kopiert werden? Der Programmierer muss dies wissen und wenn er es nicht tut
strncpy()
oderstrlcpy()
nicht retten wird.strlcpy()
undstrlcat()
sind nicht Standard, weder ISO C noch POSIX. Ihre Verwendung in tragbaren Programmen ist daher unmöglich. Tatsächlichstrlcat()
gibt es zwei verschiedene Varianten: Die Solaris-Implementierung unterscheidet sich von den anderen für Randfälle mit der Länge 0. Dies macht sie noch weniger nützlich als sonst.quelle
strlcpy
ist schneller alsmemcpy
auf vielen Architekturen, insbesondere wenn diememcpy
Kopien unnötige nachfolgende Daten kopieren.strlcpy
Gibt auch zurück, wie viele Daten Sie verpasst haben, wodurch Sie möglicherweise schneller und mit weniger Code wiederhergestellt werden können.n
in meinem memcpy-Aufruf ist die genaue Anzahl der zu schreibenden Bytes angegeben, sodass die Effizienz auch kein so großes Problem darstellt.strlcpy
jedes Mal , wenn Sie es brauchen verwendenmemcpy
undstrlen
das ist auch in Ordnung, aber warum dann beim Anhaltenstrlcpy
, nicht wahr brauchen einememcpy
Funktion, können Sie entweder die Bytes einzeln kopieren. Die Referenzimplementierung durchläuft die Daten im Normalfall nur einmal, was für die meisten Architekturen besser ist. Aber selbst wenn die beste Implementierungstrlen
+ verwendetmemcpy
, ist dies immer noch kein Grund, einen sicheren Strcpy nicht immer wieder neu implementieren zu müssen.strlcpy
wenn Sie im guten Fall (der die Mehrheit sein sollte) nur einmal über die Eingabezeichenfolge streichen und im schlechten Fall zweimal, mit Ihremstrlen
+memcpy
gehen Sie immer zweimal darüber. Ob es in der Praxis einen Unterschied macht, ist eine andere Geschichte.Ich denke, Ulrich und andere denken, dass es ein falsches Gefühl der Sicherheit geben wird. Das versehentliche Abschneiden von Zeichenfolgen kann Auswirkungen auf die Sicherheit anderer Teile des Codes haben (wenn beispielsweise ein Dateisystempfad abgeschnitten wird, führt das Programm möglicherweise keine Vorgänge für die beabsichtigte Datei aus).
quelle
malware.exe.jpg
bis abschneidenmalware.exe
.Es gibt zwei "Probleme" im Zusammenhang mit der Verwendung von strl-Funktionen:
Die c1x Standard Draft Writer und Drepper argumentieren, dass Programmierer den Rückgabewert nicht überprüfen werden. Drepper sagt, wir sollten irgendwie die Länge kennen und memcpy verwenden und String-Funktionen insgesamt vermeiden. Das Standardkomitee argumentiert, dass der sichere strcpy beim Abschneiden ungleich Null zurückgeben sollte, sofern das
_TRUNCATE
Flag nichts anderes angibt . Die Idee ist, dass Leute eher if (strncpy_s (...)) verwenden.Einige Leute denken, dass String-Funktionen niemals abstürzen sollten, selbst wenn falsche Daten eingegeben werden. Dies betrifft Standardfunktionen wie strlen, die unter normalen Bedingungen fehlerhaft sind. Der neue Standard wird viele solcher Funktionen enthalten. Die Schecks haben natürlich eine Leistungsstrafe.
Der Vorteil der vorgeschlagenen Standardfunktionen besteht darin, dass Sie wissen, wie viele Daten Sie mit strl- Funktionen verpasst haben .
quelle
strncpy_s
keine sichere Version von ist,strncpy
sondern im Grunde einstrlcpy
Ersatz.Ich glaube nicht ,
strlcpy
undstrlcat
sind betrachten unsicher oder es am wenigsten es ist nicht der Grund , warum sie nicht in glibc enthalten - schließlich, glibc enthält Strncpy und sogar strcpy.Die Kritik war, dass sie angeblich ineffizient und nicht unsicher sind .
Laut dem Secure Portability- Papier von Damien Miller:
Aus diesem Grund sind sie in glibc nicht verfügbar, aber es stimmt nicht, dass sie unter Linux nicht verfügbar sind. Sie sind unter Linux in libbsd verfügbar:
Sie sind in Debian und Ubuntu und anderen Distributionen verpackt. Sie können auch einfach eine Kopie nehmen und in Ihrem Projekt verwenden - es ist kurz und unter einer zulässigen Lizenz:
quelle
Sicherheit ist kein Boolescher Wert. C-Funktionen sind nicht vollständig "sicher" oder "unsicher", "sicher" oder "unsicher". Bei falscher Verwendung kann eine einfache Zuweisungsoperation in C "unsicher" sein. strlcpy () und strlcat () können sicher verwendet werden, ebenso wie strcpy () und strcat () sicher verwendet werden können, wenn der Programmierer die erforderlichen Zusicherungen für eine korrekte Verwendung bietet.
Der Hauptpunkt bei all diesen C-String-Funktionen, Standard und nicht so Standard, ist das Niveau, bis zu dem sie die sichere Verwendung erleichtern . strcpy () und strcat () sind nicht trivial sicher zu verwenden; Dies wird durch die Häufigkeit bewiesen, mit der C-Programmierer im Laufe der Jahre Fehler gemacht haben und böse Sicherheitslücken und Exploits aufgetreten sind. strlcpy () und strlcat () sowie strncpy () und strncat (), strncpy_s () und strncat_s () sind etwas einfacher sicher zu verwenden, aber dennoch nicht trivial. Sind sie unsicher / unsicher? Bei falscher Verwendung ist nicht mehr als memcpy ().
quelle