Wenn Sie sprintf() oder vsprintf() verwenden, müssen Sie zunächst einen Puffer zuweisen, und Sie müssen sicherstellen, dass der Puffer groß genug ist, um die Sprintf-Schreibvorgänge zu enthalten. Andernfalls überschreibt sprintf den Speicher, der hinter dem Ende des Puffers liegt.
char* x = malloc(5 * sizeof(char));
sprintf(x,"%s%s%s", "12", "34", "56"); // writes "123456" +null but overruns the buffer
... schreibt die ‚6‘ und das abschließende null
über das Ende des Raumes zu x
zugeordnet, entweder eine andere Variable oder verursacht einen Segmentation Fault korrumpieren.
Wenn Sie Glück haben, wird es auf Speicher zwischen zugewiesenen Blöcken trampeln, und wird nicht schaden - dieses Mal. Dies führt zu zeitweiligen Fehlern - die schwierigste Art zu diagnostizieren. Es ist gut, ein Tool wie ElectricFence zu verwenden, das verursacht, dass Überläufe fehlschlagen - schnell.
Ein nicht böswilliger Benutzer, der eine überlange Eingabe bereitstellt, kann dazu führen, dass sich das Programm auf unerwartete Weise verhält. Ein böswilliger Benutzer könnte dies ausnutzen, um seinen eigenen ausführbaren Code in das System zu bekommen.
Ein Schutz dagegen ist, snprintf()
zu verwenden, der die Zeichenfolge auf die maximale Länge abschneidet, die Sie bereitstellen.
char *x = malloc(5 * sizeof(char));
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); // writes "1234" + null
Der Rückgabewert size
ist die Länge, dass würde geschrieben gewesen, wenn Platz vorhanden ist - nicht die abschließende Null- einschließlich.
In diesem Fall, wenn size
größer als oder gleich 5 ist, dann wissen Sie, dass Kürzung aufgetreten ist - und wenn Sie nicht abgeschnitten werden wollten, können Sie eine neue Zeichenfolge zuweisen und snprintf()
erneut versuchen.
char *x = malloc(BUF_LEN * sizeof(char));
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56");
if(size >= BUF_LEN) {
realloc(&x,(size + 1) * sizeof(char));
snprintf(x, 5, "%s%s%s", "12", "34", "56");
}
(das ist ein ziemlich naive Algorithmus, aber es zeigt den Punkt)
asprintf()
tut dies in einem Schritt für Sie - berechnet die Länge der Zeichenfolge, ordnet diese Menge an Speicher und schreibt die Zeichenfolge hinein.
char *x;
int size = asprintf(&x, "%s%s%s", "12", "34", "56");
In allen Fällen, wenn Sie mit x
beendet haben, müssen Sie es lösen, oder Sie lecken Speicher:
free(x);
asprintf()
ist eine implizite malloc()
, so dass Sie es funktionierte zu überprüfen, genau wie Sie mit malloc()
oder einem anderen System aufrufen würden.
if(size == -1) {
/* deal with error in some way */
}
Beachten Sie, dass asprintf()
Teil der GNU und BSD-Erweiterungen ist zu libc - man kann nicht sicher sein, es in jeder C-Umgebung zur Verfügung stehen wird. sprintf()
und snprintf()
sind Teil der POSIX und C99 Standards.
'asprintf()' und 'vasprintf()' sind GNU-Erweiterungen. Hinzugefügt das GNU-Tag. – alk
Hmm, ich frage mich, ob der Fragesteller hier die Übungen macht: http://exploit-exercises.com/nebula/level02? – jordanpg
Ein sehr guter Blogbeitrag zu diesem Thema findet sich hier: [Speicherverwaltung-in-c-und-auto] (http://insanecoding.blogspot.de/2014/06/memory-management-in-c- und-auto.html) ... übrigens. der komplette Blog ist lohnend zu lesen – antibus