Wie Sie verhindern, dass memcpy-Puffer-überlauf?
Gibt es einige binäre Puffer mit fester Größe in einem Programm, das verwendet werden, um Daten zu speichern.
Und memcpy verwendet wird, die zum kopieren der Puffer von einem zum anderen. Da die Quelle-Puffer größer sein kann als der Ziel-Puffer. Wie kann ich erkennen, ob es buffer overflow?
- Erkennen? Kennen Sie Ziel-Puffer-Größe? Dann schreiben Sie code wie diesen memcpy(src, dst, sizeof(dst))
- Vergleichen Sie die Größe der Quelle-Puffer-und Ziel-Puffer und sehen, welche größer ist?
- dass
sizeof
nur um die Größe eines Zeigers. - Behandeln Sie es als pseudocode. Es kann die Größe eines Puffer-je nach Deklaration-Stil. Mir ist klar, dass sizeof(dst *) gibt die Größe des Zeigers und sizeof(dst [123]) gibt die Puffergröße, zumindest, wenn 1 element = 1 byte.
- wenn
dst
ist ein Zeiger. Wenn es etwas anderes (z.B. ein array) wird es geben, die Größe der. - Ich war der Annahme, vielleicht falsch, dass OP war der Umgang mit Zeigern, sonst wäre es kein problem in den ersten Platz.
- IIUC, sein problem ist das Ziel, nicht die Quelle. Es scheint vernünftig zu kümmern, ob die Daten passen in das Ziel-auch wenn die Quelle ist ein array. (Keiner von denen die wirklich hilft ihm, denn auch wenn die Quelle ist ein array,
sizeof
geben wird, die Größe des kompletten Arrays, auch wenn nur teilweise ausgefüllt ist.)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie wissen, wie viel Daten in der Quelle-Puffer-und wie viel Speicherplatz in den Ziel-Puffer.
Nicht nennen
memcpy()
wenn es ist nicht genügend Speicherplatz in den Ziel-Puffer für alle Daten, die Sie kopieren möchten aus der Quelle-Puffer. (Sie haben zu entscheiden, ob es OK ist zum abschneiden der Daten, wenn die Quelle größer als das Ziel.)Wenn Sie nicht wissen, schreiben Sie den code so, dass Sie nicht wissen, wie viel Platz da ist; andernfalls ist es nicht sicher.
Beachten Sie, dass, wenn es eine chance gibt, der Quell-und Ziel-Puffer überlappen, sollten Sie
memmove()
dann ehermemcpy()
.In C++, einen skeptischen Blick auf die Verwendung
memcpy()
in den ersten Platz; das ist ein C-style-Betrieb statt C++.std::vector<>
, und nutzen Sie einfachvector2 = vector1
.insert
.insert
, dann übergeben Sie einen Zeiger auf ein element eines Vektors als Puffer, um Ihre socket -recv
Funktion. Sie haben, um sicherzustellen, dass die Größe des Vektors ist groß genug erste.resize
auf einem Vektor wird deutlich, das Byte, da ist also immer noch ein kleiner Aufwand verglichen mit dem schreiben in ein nicht initialisiertes array.Ich glaube, Sie haben drei oder vier Möglichkeiten (geben oder nehmen).
Ist die erste Wahl, um eine "sichere" Funktion für
memcpy
. Dies ist, was ich verlange im code unter meiner Aufsicht, und ich regelmäßig eine Prüfung für Sie. Ich verlange auch, dass alle Parameter überprüft werden, und alle Parameter, die geltend gemacht werden.Den Behauptungen erstellen selbst Debuggen von code. Ich möchten, dass Entwickler code schreiben; und ich will Sie nicht verschwenden Zeit mit Debuggen. So ich verlangen, daß Sie code schreiben, Debuggen selbst. Behauptet auch Dokumente, die die Dinge ziemlich gut, so dass Sie knausern auf die Dokumentation. In release-builds, die Behauptet werden entfernt, indem preporcessor Makros.
Wenn Ihr
safe_memcpy
gibt nicht 0, dann gab es einen Fehler, wie eine schlechte parameter oder potenziellen Pufferüberlauf.Die zweite Möglichkeit ist die Verwendung "sicherer" Funktionen der C-Standard. C hat "sicherer" - Funktionen über ISO/IEC TR 24731-1 Bounds-Checking Interfaces. Auf konforme Plattformen, können Sie einfach anrufen
gets_s
undsprintf_s
. Sie bieten ein konsistentes Verhalten (wie immer dafür ein string istNULL
beendet) und die konsequente Rückkehr-Werte (wie 0 bei Erfolg oder einerrno_t
).Leider, gcc und glibc nicht konform zum C-Standard. Ulrich Drepper (einer der glibc-maintainer) genannt bounds-checking interfaces "schrecklich ineffizient BSD Mist", und Sie wurden nie Hinzugefügt.
Die Dritte Wahl ist, um die Plattform "sicherer" - Schnittstellen, falls vorhanden. Auf Windows -,, die passiert werden die gleichen wie jene, die in ISO/IEC TR 24731-1 Bounds-Checking Interfaces. Sie haben auch die String-Bibliothek Sicher.
Auf Apple und BSD haben Sie nicht eine "sicherere" Funktion für
memcpy
. Aber Sie haben safer string-Funktionen wiestrlcpy
,strlcat
und Freunde.Unter Linux, die vierte Wahl ist, um FORTIFY_SOURCE. FORTIFY_SOURCE verwendet die "sicherere" Variante von high-risk-Funktionen wie
memcpy
,strcpy
undgets
. Der compiler verwendet die sicherere Variante, wenn es ableiten kann, die Ziel-Puffer-Größe. Wenn die Kopie überschreiten würde, die Ziel-Puffer-Größe), dann ruft das Programmabort()
. Wenn der compiler nicht ableiten, das Ziel-Puffer-Größe, dann die "sicherere" Variante (N) werden nicht verwendet.Deaktivieren FORTIFY_SOURCE für die Prüfung, sollten Sie das Programm kompilieren mit
-U_FORTIFY_SOURCE
oder-D_FORTIFY_SOURCE=0
.Sollten Sie immer wissen, und überprüfen Sie die src-und dest-Puffer Größe !
n
sollte nie größer sein, alssrc
oderdest
Größe.Wenn zum Beispiel Sie haben:
Ziel 4 bytes Größe
Quelle 5 bytes Größe
Können Sie stellen Sie sicher, dass Sie maximal 4 bytes zur Ziel-Puffer:
Basierend auf Ihrer Anwendung könnten Sie auch sicherstellen, dass die restlichen Daten kopiert werden zu einem späteren Zeitpunkt, oder können Sie überspringen, wenn einige Daten können ignoriert werden.