Überlauf über scanf("%8s", string)?
Ich weiß, es ist möglich zu überlaufen ordentlichen code:
char string[9];
scanf("%s", string).
Aber ist es möglich, mit überlauf scanf("%8s", string)? 8 ist nur ein Beispiel.
Ich weiß, "%8s" funktioniert wie eine Abgrenzung, aber ich merke auch, wenn ich den input-string länger als 8 Zeichen, wird das Programm beendet durch:
* stack smashing detected *: ./ein.aus gekündigt
======= Backtrace: =========
...
Offensichtlich gibt es ein flag, das erkennt stack-smashing eingeschaltet, indem Sie GCC standardmäßig. Da dies ist ein stack-smashing, dann meine Vermutung ist, dass es immer noch möglich zu überlaufen und beliebigen code ausführen.
Im Gegensatz zu normalen überlauf, mangles der Aufrufer scanf("%s"), wenn scanf("%8s") können überlauf, überlauf wird innerhalb der scanf-Funktion, so dass, wenn scanf versuchen, wieder die Kontrolle gewonnen.
Aber scanf ist eine syscall, die erfordert, dass der Modus-Schalter (Umschaltung vom Benutzermodus in den Kernelmodus), und intern wird Sie nennen Dinge wie Lesen von stdin, etc. Also nicht sicher, ob wir können-overflow im kernel-Modus oder so..
Kommentare sind herzlich willkommen!!
UPDATE >>
char string[9] angenommen im obigen Beispiel. char string[8] im folgenden code.
Die Frage ist wirklich über die scheinbare widersprüchliche Geschichte zwischen sicheren scanf("%8s") und GCC Abtreibung aufgrund stack-smashing.
Vereinfachte code:
void foo(pass some pointer) {
char input[8];
int input_number = 0;
while (1) { //looping console
printf some info;
scanf("%8s", input);
input_number = atoi(input);
if ((strlen(input) == 1) && (strncmp(input, "q", 1) == 0)) {
input_number = -1;
}
switch (input_number) {
case -1: to quit the console if input = 'q';
default: to print info that pointer refers to;
...
}
}
}
Hinweis:
- foo aufgerufen wird, der von jemand anderem.
- Obwohl der string ist 8 bytes in real
code mit "%8s", ich glaube nicht, dass dies
führen zu zerschlagen.
wie bereits mehrfach in den Antworten, ein nul-byte Hinzugefügt, so benötigen Sie ein 9-Zeichen-Puffer zu akzeptieren, bis zu 8 Zeichen der Eingabe.
Wie viele Menschen haben darauf hingewiesen, den Ihre Annahme, in "Note 2." ist falsch. Das Beispiel ermöglicht es einem einzelnen byte-überlauf, was gcc zu erkennen.
Sie Jungs sind richtig. Ich habe es getestet mit ein noch einfacheres Programm, aber es irgendwie nicht zum Absturz der letzten Zeit habe ich versucht. Wenn ich jetzt enter "12345678" für string[8] und scanf(%8s) es stürzt ab, weil der stack-smashing! Hier ist also die Lektion gelernt. Smashing bedeutet nicht unbedingt, es gibt eine stack-overflow-Angriff.
Obwohl der buffer geschieht, werden auf dem stack in diesem Fall, der Programmier-Fehler ist ein buffer overflow nicht zu einem stack-überlauf. Ich retagged die Frage entsprechend.
InformationsquelleAutor Figo | 2009-11-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sehen http://www.opengroup.org/onlinepubs/009695399/functions/scanf.html:
Damit es nicht überlaufen-ein 9-byte-string-Puffer.
da hast du einen Fehler gemacht. Zeigen Sie Ihren code!
code gepostet.
irgendwie sind Sie nicht zu verstehen. "%8s" speichert bis zu 9 bytes, also brauchen Sie einen neun-Zeichen-array.
InformationsquelleAutor ysth
Nicht immer Verwendung
scanf
(oderfscanf
für diese Angelegenheit), wenn Sie möchten, dass Ihre Eingabe robust.Sollten Sie mit Hilfe
fgets
(oder ein ähnlich "geschützt vor buffer-overflow" - Variante), dann verwenden Siesscanf
.Das Hauptproblem mit
scanf
undfscanf
ist, dass Ihre Datei-Zeiger am Ende kann in eine unbestimmte position ein, wenn die Zeile nicht dem erwarteten format (D. H., wenn diescanf
fehlschlägt). Mit derfgets/sscanf
Methode, es ist viel einfacher, um zu garantieren, dass Sie an eine Grenze, ohneftell
undfseek
zu bewegen, die Datei.Bezüglich Ihrer spezifischen Abfrage, ob der Puffer überläuft, der C-standard sagt:
So, für einen
"%8s"
- format, benötigen Sie ein 9-Zeichen-array.Ich vermute, Sie haben ein anderes problem in deinem code. Mit einem test-Programm:
Bekomme ich:
Wenn ich das gleiche Programm verwenden
"%8s"
ich bekommen (für genau den gleichen Eingang):Beschreiben Sie "robust"? Geben Sie einige Beispiele?
Holen Sie sich Ihren input als Linien. (2) Sicherstellen, dass Sie ganze Zeilen (\n char am Ende), Fehler, ansonsten mit "Zeile zu lang". (3) die Verwendung sscanf on line - Sie können dies tun, so oft wie Sie möchten auf der Linie, ohne sich Gedanken über die zugrunde liegende Datei.
Ich auch testen, eine ähnlich vereinfachte code wie Sie haben und GCC nicht beschweren stack-smashing.. ich habe geschrieben orig-code und die Sache ist zur Laufzeit gibt es den GCC beschweren, wenn ich die Eingabe 12345678 (Hinweis: in echten code char string[8]).
benötigen Sie ein 9-Zeichen-array zum speichern eines 8-Zeichen-Strings. Das ist, weil ein 8-Zeichen-Strings bestehen aus 8 Zeichen (offensichtlich) und ein null-Abschlusszeichen (nicht so offensichtlich). Wenn Sie es ändern, um char string[9], Sie sollten keine Probleme haben.
InformationsquelleAutor paxdiablo
wenn die Zeichenfolge zugeordnet wird, die für weniger als 8 Urkunden wird es sicherlich überschreiben des Puffers auch scanf nicht Anhängen eines null-terminator. Aber solange Sie über genügend Platz im string für Ihr Wert sollten Sie nicht bekommen eine overwright.
Eigentlich denke ich, scanf wird ein '\0' am Ende. C-standard sagt, "ein abschließendes null-Zeichen, die automatisch Hinzugefügt werden.", auch zitiert von paxdiablo
Ich meinte, wenn Sie nicht auch ein Platz für die null.
Wenn Sie nicht über ein Feld für die null, es wird es dort egal (wobei einige andere Teil des Stapels, wenn nötig).
char string[9] sollte in Ordnung sein.
InformationsquelleAutor rerun
Als ysth darauf hingewiesen, dass der array sollte in der Lage sein, um die Zeichenfolge enthalten und des abschließenden null-Zeichen, so dass mit einem 8-byte-Arrays (vor allem, wenn es auf dem Stapel reserviert, wie es in deinem code) ist sehr wahrscheinlich zu mess es.
InformationsquelleAutor Tal Pressman