Diskussion:Pufferüberlauf

Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 2. April 2009 um 10:50 Uhr durch Uncle Pain (Diskussion | Beiträge) (Stack Overflow?). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Letzter Kommentar: vor 16 Jahren von Uncle Pain in Abschnitt Stack Overflow?

Ich habe gerade Assembler aus der Liste der besonders gefährlichen Programmiersprachen gelöscht, weil Assemblersprache einem im Gegensatz zu C/C++ volle Kontrolle über die CPU, also auch Aufruf- und Übergabekonventionen, Überlaufflags usw., an die ich in C nicht drankomme, gibt, sodaß ein Programmierer, der weiß, was er tut, damit weniger falsch machen kann als mit C/C++. Mh 20:09, 22. Jun 2004 (CEST)

Das halte ich so für Blödsinn. Wer weiß, was er tut hat demnach mit gar keiner Programmiersprache (Sicherheits-)Probleme. Der Sicherheitsvorteil höherer Sprachen (als C und C++) liegt doch darin, dass diese den Zugriff auf solche Details gar nicht erst ermöglichen. Die Gefahr Fehler zu machen ist doch bei Assembler noch wesentlich höher als bei C. --Cyclonus 23:36, 17. Jul 2005 (CEST)
Ich gebe Mh da recht, denn die gefährlichsten C/C++ Programmierer sind die, die von wesentlich weiter abstrahierenden Sprache(n) auf C/C++ umgeschult wurden (eg. Cobol, Ada, Pascal, Oberon), aber wie so oft, nur halbherzig. Wer aber von Assembler oder Fortran (also nicht Fortran95, sondern Fortran) mehr versteht, als nur, das es cool ist, der weiß auch um die Effekte von Pointern, kennt negative Indizes und weiß vor allem, was man wo wie machen kann. Allerdings kann man mit Assembler in den falschen Händen noch viel mehr falsch machen, als in C oder C++ - vor allem, wenn einem dank "managed C++" vom Visual Studio .net eine trügerische Sicherheit vorgegaukelt wird. -- Jens Rehsack, 13.12.06, 18:52 CET

Benennung

Gäbe es grundsätzliche Argumente, die gegen die Verschiebung zur deutschen Bezeichnung Pufferüberlauf sprächen? Stern 20:53, 22. Jun 2004 (CEST)

hmm - der google-score (sic) ist ca. 40,000 zu ca. 10,000 für buffer overflow. aber prinzipiell dagegen wäre ich nicht. grüße, Hoch auf einem Baum 05:28, 23. Jun 2004 (CEST)
der google-score für "buffer overflow" ist 1,390,000 - nicht nur das spricht für eine Rückkehr zum Titel "Buffer Overflow" - ich höre den Begriff Pufferüberlauf so gut wie nie, ich glaube, er ist allgemein nicht besonders gebräuchlich. Drhankey 19:29, 2. Aug 2005 (CEST)
mE spricht auch nichts dagegen, solange der Begriff Buffer Overflow im Artikel nicht vollständig getilgt wird (was hier aber wohl nicht zur Debatte steht). lg --Hubi 08:43, 23. Jun 2004 (CEST)
Von mir aus gerne, solange weitergeleitet wird... Mh 20:19, 17. Jul 2004 (CEST)
Ist erledigt. Man müsste im Text nochmal die Buffer Overflows durch Pufferüberläufe ersetzen. Stern 20:23, 17. Jul 2004 (CEST)

Was in dem Artikel noch fehlt

  • Overflows mit hilfe von umgebungsvariablen (wenn der Buffer zu klein ist)
Vielleicht solltest Du dann etwas dazu schreiben, da man sonst bestenfalls raten kann, was Du damit meinst. --Cyclonus 23:36, 17. Jul 2005 (CEST)

Die "Zufallszahlbarriere" wird meines Wissens in Anlehnung an die Kanarienvogel, die Bergarbeiter mit in die Minenschächte nahmen, um durch deren Ableben auf gefährliche Gase hingewiesen zu werden, auch "Canary" genannt. --Anonymous

Fehler im Artikel??

im artikel steht, das der stack bei aufruf von gets so aussieht:


Rücksprungadresse
1000. Zeichen
...
3. Zeichen
2. Zeichen
1. Zeichen  Stackpointer

aber gets nimmt als parameter nicht line[] selber sonden den zeiger darauf an. (steht ja auch in dem kommentar /* gets erhält Zeiger, keine Überprüfung */) also steht imho hinter der rücksprungadresse nur der zeiger. so kann auch kein pufferüberlauf entstehen. wenn ich das falsch sehe bitte ich um aufklärung.

Ja, das ist so falsch. Allerdings liegt line[] natürlich auch auf dem Stack, da es sich um eine lokale Variable handelt. Allerdings müsste sie nach der Beschreibung oberhalb der Rücksprungadresse liegen. Wächst der Stack nach oben ist es fast richtig, nur fehlt dann der Zeiger zwischen line[] und der Rücksprungadresse. --Cyclonus 23:14, 17. Jul 2005 (CEST)
Mit Rücksprungadresse ist hier (wahrscheinlich) nicht die Adresse zur Rückkehr aus gets() sondern der aus input_line() gemeint. Die Position des Stackpointers ist dann allerdings verwirrend, da der auf lokale Variablen oder den Parameter von gets() zeigen sollte. --Cyclonus 23:23, 17. Jul 2005 (CEST)
Gemeint ist wohl der Stack vor dem Aufruf von gets() und nach dem Rücksprung. Hab's klarer formuliert.--Gunther 11:22, 15. Sep 2006 (CEST)

Heap-Überlauf Beispiel

Habe soeben noch eine weitere Lösung zur Vermeidung eines Überlaufs hinzugefügt. Ist die Lösung mit strlen() überhaupt korrekt? IMHO gibt's da ebenfalls ein Problem, wenn die Nullterminierung im Eingangsstring fehlt. --Kasper4711 13:56, 16. Nov 2005 (CET)

Natürlich gibt es dann ein Problem. Nämlich dass strlen() theoretisch niemals fertig wird, irgendwann einen Absturz verursacht oder malloc() NULL zurückliefert. Eventuell sollte man alle Beispiele entfernen, schließlich ist Wikipedia nicht der Ort für Tutorials und auch keine gutgemeinten Ratschläge. Dass jemand aufgrund dieses Artikels seinen Code ändert halte ich für unwahrscheinlich, zumindest ist es dann sicher schon Hopfen und Malz verloren. Im Übrigen verursacht jede Variante einen Absturz, wenn s nicht auf ein gültiges Speicherobjekt zeigt oder dieser nicht als lesbar (z.B. write-only, execute-only) gemappt ist. Generell gilt, wenn die Interface-Spezifikation einen String verlangt, dann muss man auch einen String übergeben, d.h. dies durch den umgebenden Code sicherstellen. Wer "strlen(NULL)" oder "strlen(malloc(100))" schreibt, dem ist mit C nicht zu helfen. Bezüglich deiner Variante: Sowas wie "#define BUFSIZE 128" ist alles andere als ratsam, den String einfach so abzuschnippeln ist auch nicht wirklich sinnvoll und den Puffer mit Nullen aufzufüllen, das macht strncpy() doch schon. Du willst doch nur den String garantiert terminieren, dafür reicht "buf[BUFSIZE - 1] = 0;". Von den ganzen Low-Level-Varianten ist letztlich nur strlcpy() empfehlenswert. Letztlich gehörte diese Frickelei aber, glaube ich, nicht in eine Enzyklopädie und im echten Leben sollte man gefälliste eine vernünftige String-Bibliothek benutzen. --Cyclonus 08:20, 4. Dez 2005 (CET)
strlen(NULL) dürfte sogar noch "gut" gehen... Bzgl. strncpy und Nullterminierung hast Du natürlich Recht. Ich persönlich finde nix Anstössiges am #define BUFSIZE, ist IMHO gängige C-Praxis. Im echten Leben gibt's nicht immer eine "vernünftige" String-Bibliothek, und wenn, dann implementiert diese ja gerade die sicheren Operationen, um die es hier geht. Und strlcpy ist halt nicht überall vorhanden. Dennoch habe auch ich nichts gegen eine Entfernung der Beispiele einzuwenden. Andere Meinungen? --Kasper4711 10:37, 6. Dez 2005 (CET)

In diesem Artikel und Heap Overflow waren momentan quasi die gleichen Texte. Ich habe aus Heap Overflow wieder einen Redirect gemacht. Meinetwegen kann man den Artikel auch wieder auslagern, aber zwei mal der gleiche Inhalt kann nur schief gehen ;-) --Boris23 18:48, 20. Dez 2005 (CET)

Ich bin eher für Auslagern. Stern 13:17, 7. Mär 2006 (CET)

Frage

Ich meine man kann sowas wie ein Buffer Overflow auch erzeugen in dem man einen Pointer auf einem vom Betriebssystem genutzten Adressraum Bzw, Adresse zeigen lässt (Bei windows). Ist das richtig? Ist das auch ein Bufferoverflow oder was anderes? مبتدئ 17:45, 3. Apr. 2007 (CEST)Beantworten

Nein, das geht nicht, jeder Prozess hat einen gewissen Speicherbereich, auf den er zugreifen darf. Soweit ich weiß, sitzt die Überprüfung dafür in der CPU, genauer in der Memory Management Unit. -84.58.131.126 02:03, 13. Jan. 2009 (CET)Beantworten

Sicherheit in C++

Im Artikel wird die Sicherheit in C++ ja ziemlich niedergeschmettert: "Daneben stellt der (im Falle von C++) komplexe Sprachumfang und die Standardbibliothek sehr viele fehleranfällige Konstrukte zur Verfügung, zu denen es in vielen Fällen kaum eine Alternative gibt." "Im Fall von C und C++ enthält die Standardbibliothek eine Anzahl von gefährlichen Funktionen, die zum Teil gar keine sichere Verwendung zulassen und zu denen zum Teil keine Alternativen bestehen." Bei C sehe ich es ja ein, aber wenn man modernes C++ programmiert (also keinen blanken Zeiger, C-Arrays oder Ähnliches), wo sind denn da die fehleranfälligen Konstrukte? Klar, der C-Teil von C++, aber wenn's nur das ist, sollte man das doch klarstellen, oder nicht?

So, hab's ein bisschen geändert und es hat anscheinend auch die Sichtung überstanden :-) Geändert hab ich den mittleren Teil der Sektion "Programmiersprachen", für Näheres siehe http://de.wikipedia.org/w/index.php?title=Puffer%C3%BCberlauf&diff=55252202&oldid=54652267 -84.58.131.126 01:59, 13. Jan. 2009 (CET)Beantworten


Stack Overflow?

Die Seite hat etwas Schieflage. Im Gegensatz zur Heap-Verwaltung gehört der "Stack Overflow" m.E. zunächst zur Hardware, erst dann zu Programmiertechniken (auch wenn C nicht ohne Pointer auskommt).

"Stack Overflow" (besser eigentlich "Stack Underflow" oder "Underrun") hat vor C zunächst etwas mit Hardware zu tun. Es ist ein Grundproblem bei der Arbeit in Assembler. Der Stack Pointer wird beim Einstieg (RCALL irgendwas) in ein Unterprogramm (in Hardware) erniedrigt (er läuft im RAM von oben nach unten), beim Ausstieg mit RET oder RETI wird er wieder erhöht. Das geht vollautomatisch, i.a. ohne daß der Programmierer darauf Einfluß nimmt.

Im Bereich der Winzlinge der Embedded Controller (z.B. ATMEL ATtiny, Microchip PIC12 etc.) programmiert man auch in Zukunft in Assembler. Man spart sich Probleme, die ein Compiler verursacht und ist code-effizienter. Der Stack solcher Prozessoren wird meist in Hardware verwaltet. Und genau hier passieren die dümmsten Fehler, da noch immer ein Programmierstil mit relativen Sprüngen (RJMP) gelehrt wird, der Stack Overflows geradezu provoziert.

Ein Problem entsteht immer dann, wenn man mit RJMP aus einem Unterprogramm herausspringt, aber nie wieder dorthin zurückkehrt. Der Stack füllt sich jedesmal ein Stück, wenn dieser Fehler auftritt. Irgendwann sind dann die paar Byte RAM voll: Stack Overflow und Absturz.

Nur wenn man sich an eine sauber gekapselte Unterprogramm-Struktur hält, wird man solche Fehler, die gemeinerweise oft erst nach einigen Stunden auftreten, meistern.

RCALL beispiel  ; Aufruf eines Unterprogramms
...
beispiel:  ; Beginn des Unterprogramms
...
RET  ; Ende des Unterprogramms

Es gibt sogar eine Eselsbrücke: Wenn im Programm nur ein einziges RJMP vorhanden ist - nämlich in der mainloop, dann ist Stack-Overflow ausgeschlossen.

(Die Mainloop sieht bei den Winzlingen oft so aus:

mainloop:  ; hier verweilen und auf Interrupts warten
WDR  ; Watchdog Reset verhindern, wenn alles OK
RJMP mainloop

)

Mit PUSH und POP sichert man übrigens das Statusregister (ATMEL: SREG) zu Beginn einer Interrupt-Behandlung. Auch wichtig für saubere Arbeit. Einziges Problem in Assembler: Alle Register sind "static". Um den Überblick zu behalten, benutzt man besser nicht die tatsächlichen Registernamen, sondern eigene Kreationen (Beispiel .DEF meinreg = r19).

-- Heinzelmann 13:03, 1. Apr. 2009 (CEST)Beantworten

Was du hier beschreibst, ist auch ein Stack-Überlauf. Rein von der wörtlichen Bedeutung des Namens ist es eigentlich auch die richtigere Bedeutung – leider ist es aber so, dass auch die Angriffsart denselben Namen bekam. Gut, bei ihr wird auch ein Stack überschrieben, aber er läuft nicht über im klassischen Sinne. --Uncle Pain 15:58, 1. Apr. 2009 (CEST)Beantworten
Die Bezeichnung Stack-Überlauf wird im Artikel gar nicht verwendet. Es geht um Heap-Überläufe (also das Überschreiten von Heap-Speicherbereichen) und andere Puffer-Überläufe (die mit lokalen Variablen auch auf dem Stack passieren können). Ein Stacküberlauf ist, wie du richtig erwähnt hast, etwas anderes. Der häufigste Fall dafür ist übrigens ein ganz trivialer, der auch in Hochsprachen auftritt: Nicht terminierende Rekursion. -- PaterMcFly Diskussion Beiträge 16:48, 1. Apr. 2009 (CEST)Beantworten
Huch, mir fiel gar nicht auf, dass der Begriff im Artikel gar nicht vorkommt :) Damit verstehe ich Heinzelmanns Einwand noch weniger. Wobei ich sagen muss, wenn man bei den Pufferüberlauf-Angriffen u. A. vom Heap-Überlauf spricht, wäre es auch konsequent, den Pufferüberlauf auf dem Stack auch als Stack-Überlauf zu bezeichnen. In meinen Augen ist Überlauf aber generell irgendwie das falsche Wort; Überschreibung oder Grenzüberschreitung fände ich passender. --Uncle Pain 10:50, 2. Apr. 2009 (CEST)Beantworten