Frage

Aus man gets:

Niemals Get () verwenden. Da es unmöglich ist, zu sagen, ohne die Daten im Voraus zu kennen, wie viele Charaktere erhalten (), wird () gelesen werden, und weil Get () die Charaktere weiterhin am Ende des Puffers speichert, ist es äußerst gefährlich zu verwenden. Es wurde verwendet, um die Computersicherheit zu brechen. Verwenden Sie stattdessen fGets ().

Fast überall, wo ich sehe scanf so verwendet werden, wie das gleiche Problem haben sollte (Pufferüberlauf/Pufferüberlauf): scanf("%s",string). Dieses Problem besteht in diesem Fall? Warum gibt es keine Hinweise darauf in der scanf Mann Seite? Warum GCC nicht warnt, wenn Sie dies zusammenstellen -Wall?

PS: Ich weiß, dass es eine Möglichkeit gibt, in der Formatzeichenfolge die maximale Länge der Zeichenfolge mit anzugeben scanf:

char str[10];
scanf("%9s",str);

Bearbeiten: Ich bitte nicht, festzustellen, ob der vorhergehende Code richtig ist oder nicht. Meine Frage ist: wenn scanf("%s",string) Ist immer falsch, warum gibt es keine Warnungen und es gibt nichts dran auf der Mannseite?

War es hilfreich?

Lösung

Die Antwort lautet einfach, dass niemand den Code in GCC geschrieben hat, um diese Warnung zu produzieren.

Wie Sie betonen, warnt eine Warnung für den spezifischen Fall von "%s" (ohne Feldbreite) ist ziemlich angemessen.

Beachten Sie jedoch, dass dies nur für den Fall von der Fall ist scanf(), vscanf(), fscanf() und vfscanf(). Dieser Formatspezifizierer kann mit vollkommen sicher sein mit sscanf() und vsscanf(), Daher sollte die Warnung in diesem Fall nicht ausgestellt werden. Dies bedeutet, dass Sie es nicht einfach dem vorhandenen Analysecode "SCANF-Format-String" -Analyse hinzufügen können. Sie müssen das in Optionen "FSCANF-Format-String" und "SSCANF-Format-String" aufteilen.

Ich bin sicher, wenn Sie einen Patch für die neueste Version von GCC produzieren, hat es eine gute Chance, akzeptiert zu werden (und natürlich müssen Sie auch Patches für die GLIBC -Header -Dateien einreichen).

Andere Tipps

Verwendung gets() ist niemals sicher. scanf() kann sicher verwendet werden, wie Sie in Ihrer Frage gesagt haben. Es ist jedoch ein schwierigeres Problem, den Compiler zu trainieren, wenn Sie es sicher verwenden (z. B. wenn Sie anrufen scanf() In einer Funktion, in der Sie den Puffer und eine Zeichenzahl als Argumente übergeben, kann es nicht in der Lage sein, es zu sagen); In diesem Fall muss man davon ausgehen, dass Sie wissen, was Sie tun.

Wenn der Compiler die formatierende Zeichenfolge von betrachtet scanf, Es sieht eine Schnur! Dies setzt voraus, dass die Formatierungszeichenfolge nicht zur Laufzeit eingegeben wird. Einige Compiler wie GCC haben eine zusätzliche Funktionalität, um die Formatierungszeichenfolge zu analysieren, wenn sie zur Kompilierungszeit eingegeben werden. Diese zusätzliche Funktionalität ist nicht umfassend, da in einigen Situationen ein Laufzeitaufwand erforderlich ist, das ein Nein für Sprachen wie C ist, können Sie beispielsweise eine unsichere Verwendung erkennen, ohne in diesem Fall einen zusätzlichen versteckten Code einzuführen:

char* str;
size_t size;
scanf("%z", &size);
str = malloc(size);
scanf("%9s"); // how can the compiler determine if this is a safe call?!

Natürlich gibt es Möglichkeiten, sicheren Code mit zu schreiben scanf Wenn Sie die Anzahl der zum Lesen zu lesen angeben und genügend Speicher gibt, um die Zeichenfolge zu halten. Im Falle des gets, Es gibt keine Möglichkeit, die Anzahl der zum Lesen zu gelesenen Zeichen anzugeben.

Ich bin mir nicht sicher, warum die Mannseite für Scanf die Wahrscheinlichkeit eines Pufferüberschritts nicht erwähnt, aber Vanilla scanf ist keine sichere Option. Ein eher datierter Link - http://blogs.msdn.com/b/rsamona/archive/2005/10/24/4844449.aspx zeigt dies als Fall. Überprüfen Sie dies auch (nicht GCC, aber dennoch informativ) - http://blogs.msdn.com/b/parthas/archive/2006/12/06/application-crash-on-replacing-sscanf-with-sscanf-s.aspx

Es kann einfach sein, dass Scanf den Haufen Platz zuordnet, basierend auf der Lesen von Daten. Da er den Puffer nicht zuordnet und dann bis zum Lesen des Nullcharakters gelesen wird, riskiert es nicht, den Puffer zu überschreiben. Stattdessen liest es in seinen eigenen Puffer, bis der Nullcharakter gefunden wird, und kopiert vermutlich, die am Ende der Lektüre in eine andere der richtigen Größe puffern.

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