Hallo zusammen, in dem Buch "Writing Secure Code" habe ich einen Quellcode in der folgenden Art gefunden:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Frage: warum funktioniert das? Gruß Dennis
|
Anzeige
|
printf ohne ArgumenteHallo zusammen, in dem Buch "Writing Secure Code" habe ich einen Quellcode in der folgenden Art gefunden:
Frage: warum funktioniert das? Gruß Dennis
Gast
#3881804
Dennis S. schrieb: > Frage: warum funktioniert das? warum sollte das nicht funktionieren? Er nimmt einfach für jedes % das nächste Element auf dem Stack. Ob sie vorher dort abgelegt wurden spielt dabei keine rolle. Peter II schrieb: > warum sollte das nicht funktionieren? Warum sollte es? Wenn ich nichts zum Ausgeben angebe, könnte es ja auch sein, dass nichts ausgegeben wird. > Er nimmt einfach für jedes % das nächste Element auf dem Stack. Ob sie > vorher dort abgelegt wurden spielt dabei keine rolle. Danke, das ist eine Erklärung.
Gast
#3881816
Dennis S. schrieb: >> warum sollte das nicht funktionieren? > Warum sollte es? Wenn ich nichts zum Ausgeben angebe, könnte es ja auch > sein, dass nichts ausgegeben wird. leider gibt es für solche Funktionen keine Möglichkeit zu prüfen, wie viele Elemente übergeben wurden. Peter II schrieb: > Er nimmt einfach für jedes % das nächste Element auf dem Stack. Allgemeiner: er nimmt das nächste Argument irgendwoher. Auf einer Architektur mit Speicherverwaltung könnte das ggf. auch einen Trap auslösen (weil auf Speicher zugegriffen wird, der nicht gemappt ist), aber ansonsten gibt das halt was aus, ohne dass man irgendwie vorhersagen kann, was es wirklich ausgibt. Ist also eher eine wertlose Aussage … Das funktioniert nur, solange es in der letzten Funktion des Programms geschieht. Es holt mehr Argumente vom Stack als vorher draufgelegt wurden, die Probleme damit hätten die folgenden Funktionen.
Gast
#3881860
Jobst Quis schrieb: > Das funktioniert nur, solange es in der letzten Funktion des Programms > geschieht. Es holt mehr Argumente vom Stack als vorher draufgelegt > wurden, die Probleme damit hätten die folgenden Funktionen. nein, denn bei cdecl räumt der Aufrufe der Stack wieder auf und diese kennt ja die Paramter. http://de.wikipedia.org/wiki/Aufrufkonvention#stdcall Ich würde mal sagen: Ob das 'funktioniert' oder nicht, hängt davon ab, was man als 'funktioniert' definiert. Gibt man sich mit irgendeinem Ergebnis zufrieden, dann kann man das 'funktioniert' nennen. Garantie gibt es dafür keine. In keiner irgendwie definierten Form. C an sich kennt noch nicht mal einen Stack. Ein Stack ist etwas, was die meisten Plattformen benutzen. Aber in der kompletten Sprachdefinition wird an keiner Stelle ein Stack erwähnt oder gefordert. Interessant wäre höchstens, worum es im Kontext dieses präsentierten Code-Schnipsels im Buch überhaupt geht. WEnn das dort als abschreckendes Beispiel benutzt wird, wie man es nicht macht, dann ist das ok. Aber auf keinen Fall kann das ein Beispiel für auch nur entfernt sinnvolles programmieren sein. Vor allen Dingen nicht in einem Buch mit dem Titel "Writing Secure Code". Karl Heinz schrieb: > Ich würde mal sagen: > Ob das 'funktioniert' oder nicht, hängt davon ab, was man als > 'funktioniert' definiert. > Gibt man sich mit irgendeinem Ergebnis zufrieden, dann kann man das > 'funktioniert' nennen. > > Garantie gibt es dafür keine. In keiner irgendwie definierten Form. Steht so aucj in der *printf Dokumentation. Und je nach System funktioniert das auch nicht sondern ergibt einen Segmentation Fault o.ä., und wenn ich mal mehr%-Argumente hab als Parameter dann ist "funktionieren" die absolute Ausnahme. Übrigens ist "View the Stack" ziemlicher Unsinn, weil es Vorsausetzungen an das Hostsystem und die Calling-Convention macht, die i.d.R nicht zutreffen. Ergo: Das Buch / Tutorial das bereits bei so elementaren Dingen Käse verzapft gehört in die Tonne! So ein Hum-Buch schadet mehr als es nützt. Johann L. schrieb: > Ergo: Das Buch / Tutorial das bereits bei so elementaren Dingen Käse > verzapft gehört in die Tonne! Dennis S. schrieb: > in dem Buch "Writing Secure Code" Vermutlich soll darin das Prinzip von Buffer-Overrun-Attacken demonstriert werden. Mit dem seltsamen Printf können – wenn auch nicht zuverlässig – Dinge auf dem Stack sichtbar gemacht werden, die dort nicht hingehören. Karl Heinz schrieb: > C an sich kennt noch nicht mal einen Stack. Huch? Aber der vom C-Compiler generierte x86 Assembler- bzw. Maschinencode schon, oder? Mark Brandis schrieb: > Karl Heinz schrieb: >> C an sich kennt noch nicht mal einen Stack. > > Huch? > > Aber der vom C-Compiler generierte x86 Assembler- bzw. Maschinencode > schon, oder? Natürlich. Irgendwie muss ja der Compiler die geforderte Funktionalität ja auch umsetzen. Aber der C-Standard lässt ihm da volle Freiheit, wie er das zu tun gedenkt. Stack ist da nicht gefordert. Auch die Verwendung von 2-er Komplement ist kein muss. Selbst der Zeichensatz ist weitgehend nicht definiert. Es gibt lediglich eine Aufzählung, welche Zeichen mindestens vorhanden sein müssen und das die Zeichen '0' bis '9' aufsteigende, aufeinanderfolgende Codes haben müssen. Alles andere, wie die Verwendung von ASCII ist freigestellt. Auch der Begriff 'Heap' kommt im Standard nicht vor. Genauso wie es keinen Bildschirm oder gar eine Tastatur gibt. ... Es sind ziemlich viele Dinge, die im C Standard nicht reglementiert sind. ALs Faustregel könnte man sagen: Wenn etwas auch nur im entferntesten hardwareabhängig ist, dann macht der C-Standard da einen Bogen drum herum. Das war/ist einerseits einer der Gründe für den Erfolg von C, ist aber andererseits aber auch wieder ein Nachteil. Yalu X. schrieb: > Johann L. schrieb: >> Ergo: Das Buch / Tutorial das bereits bei so elementaren Dingen Käse >> verzapft gehört in die Tonne! > > Dennis S. schrieb: >> in dem Buch "Writing Secure Code" > > Vermutlich soll darin das Prinzip von Buffer-Overrun-Attacken > demonstriert werden. Ok. In dem Beispiel bekommt man immerhin eine Warnung vom Compiler. Übler ist folgender Lapsus:
Korrekt ist
bzw.
Gast
#3882318
Es gibt auch SPARC, da werden Register-Fenster umgeschaltet beim Call. Oder /360..390, die hat keinen dedizierten Stack, aber jede Menge Register, die als Index-Register taugen. Da gibt es auch kein CALL sondern BranchAndLoadRegister. Ein Stack entsteht als verkettete Liste. R0 zeigt auf ein Array aus Pointern auf die Parameter. Übergebe ich nur den FormatString, dann zeigen die "folgenden Parameter" schlicht ins Nirvana. Zum Teil interessante Anmerkungen. Aber wie emotional manche plötzlich werden ist wirklich... unverständlich. Der Codeschnippsel ist eine Demonstration eines Stack-Overruns. Da das Buch im Microsoft Press-Verlag erschienen ist, kann man die Umgebungsbedingungen eigentlich schon recht klar definiert. Ich muss aber dazu sagen, dass ich es bisher nur überflogen habe.
Gast
#3882940
Dennis S. schrieb: > Da das > Buch im Microsoft Press-Verlag erschienen ist, Das erklärt den Scheiß --> Tonne. Die Welt besteht aus mehr als nur Microsoft, und im Embedded-Bereich (Tipp: Wie heißt dieses Seite nochmal?) spielt Microsoft keine Rolle.
Gast
#3882953
Mark 99 schrieb: > Das erklärt den Scheiß --> Tonne. > > Die Welt besteht aus mehr als nur Microsoft, und im Embedded-Bereich > (Tipp: Wie heißt dieses Seite nochmal?) spielt Microsoft keine Rolle. unter gcc funktioniert das Beispiel und wir sind hier im GCC Forum. Mark 99 schrieb: > Das erklärt den Scheiß --> Tonne. Der Auszug ist das passende Werkzeug für die passende Aufgabe oder nicht? Hast du mehr Beispiele aus dem Buch, die nicht angemessen sind? > Die Welt besteht aus mehr als nur Microsoft, und im Embedded-Bereich > (Tipp: Wie heißt dieses Seite nochmal?) spielt Microsoft keine Rolle. Hmm.. das haben meine Linux-Rechner mir gar nicht verraten. Aber: Mea Culpa, ich war im falschen Unterforum. Peter II schrieb: > unter gcc funktioniert das Beispiel Nochmal: das macht irgendwas. Mit GCC auf einer UltraSPARC ist keineswegs sicher, dass da irgendwas vom Stack angezeigt wird, denn dort werden auch bei varargs die Argumente zuerst im entsprechenden Registerfenster übergeben; der Stack wird dort nur für Funktionen mit sehr vielen Argumenten genutzt. Es gäbe weiß Gott genügend Beispiele aus der Praxis, an denen man real vorhandene (und ausnutzbare) Stack-Attacken demonstrieren kann. Klar, diese Teile sind immer auf eine bestimmte Architektur zugeschnitten, denn in aller Regel möchte man erreichen, dass Fremdcode (des Attackierenden) ausgeführt wird, bspw. indem man diesen als Maschinencode auf den Stack packt und durch gezieltes Überschreiben der Rücksprungadresse dann einen Sprung auf diesen Code provoziert.
Gast
#3882969
Jörg Wunsch schrieb: > Nochmal: das macht irgendwas. es steht nicht da das der code portable ist, aber in 99% der üblichen Hard und Software macht es das was im Kommentar steht.
Gast
#3882976
Jörg Wunsch schrieb: > Mit GCC auf einer UltraSPARC ist > keineswegs sicher, dass da irgendwas vom Stack angezeigt wird, denn > dort werden auch bei varargs die Argumente zuerst im entsprechenden > Registerfenster übergeben; der Stack wird dort nur für Funktionen > mit sehr vielen Argumenten genutzt. dann scheint die Doku von GCC aber falsch zu sein. https://gcc.gnu.org/onlinedocs/gccint/Varargs.html — Macro: __builtin_next_arg (lastarg) This builtin returns the address of the first anonymous stack argument, as type void *. If ARGS_GROW_DOWNWARD, it returns the address of the location above the first anonymous stack argument. Use it in va_start to initialize the pointer for fetching arguments from the stack. Also use it in va_start to verify that the second parameter lastarg is the last named argument of the current function. hier ist "first anonymous stack Argument" geschrieben, also wird es wohl immer über den stack laufen. Peter II schrieb: > hier ist "first anonymous stack Argument" geschrieben, also wird es wohl > immer über den stack laufen. Wenn aber die Maschine gar keinen Stack hat, wie Jörgs SPARC? Da wird dann wohl die ABI anders aussehen, und die Funktion was anderes machen, bzw. den Begriff "Stack" eher als Metabegriff auslegen.
Gast
#3883020
Rufus Τ. Firefly schrieb: > Wenn aber die Maschine gar keinen Stack hat, wie Jörgs SPARC? Da wird > dann wohl die ABI anders aussehen, die Doku ist aber von GCC und von keiner speziellen Platform > und die Funktion was anderes machen, > bzw. den Begriff "Stack" eher als Metabegriff auslegen. dann kann man auch den Begriff "Stack" von dem code als Metabegriff sehen und er macht wieder das was im Kommentar steht. Rufus Τ. Firefly schrieb: > Wenn aber die Maschine gar keinen Stack hat, wie Jörgs SPARC? SPARC-Maschinen haben durchaus einen Stack und auch ein "SP"-Register. In "altmodischer Denkweise" könnte man sogar sagen: bis zu 32 davon... Aber mal ernsthaft: wer hätte von einem Microsoft-Press Buch erwartet, daß es da drin irgendwas anderes als x86 zu lesen gäbe?
Gast
#3883043
Markus F. schrieb: > Aber mal ernsthaft: wer hätte von einem Microsoft-Press Buch erwartet, > daß es da drin irgendwas anderes als x86 zu lesen gäbe? Ich glaube hier geht es grad eher darum, dass mit zweierlei Maß gemessen wird. Der Autor des obigen Codes wird dafür kritisiert dass der Code plattformspzifisch ist und der Begriff "Stack" im Kommentar verwendet wird, wo doch garnicht alle Architekturen einen Stack kennen. Der gcc-Doku wird die Verwendung dieses Begriffes aber nachgesehen...
Gast
#3883066
Macro: __builtin_saveregs ()
Use this built-in function to save the argument registers in memory
so that the varargs mechanism can access them.
Both ISO and traditional versions of va_start must use
__builtin_saveregs
Michl schrieb: > Der Autor des obigen Codes wird dafür kritisiert dass der Code > plattformspzifisch ist und der Begriff "Stack" im Kommentar verwendet > wird, wo doch garnicht alle Architekturen einen Stack kennen. So ziemlich alle Architekturen kennen einen Stack. Der wird aber nicht auf allen Architekturen vollständig für Funktionsargumente benutzt, siehe SPARC. > Der gcc-Doku wird die Verwendung dieses Begriffes aber nachgesehen... Du wirfst da was durcheinander: Bei der Sprachdefinition von C braucht man den Begriff "Stack" tatsächlich nicht. gcc jedoch ist das "Werkzeug" - nicht die Sprache. gcc bedient sich halt im konkreten Fall eines Stacks, um Argumente zu übergeben. Aber das ist nur eine konkrete Implementierung - nichts weiter.
Gast
#3883086
Bevor jetzt alle unnötig weiterpöbeln: OP hat das Beispiel aus dem Buch auf das für seine Frage wesentliche (nämlich das printf ohne Argumente) gekürzt. Der Stack wird in dem eigentlichen Beispiel klassisch mit (sinngemäß) strcopy(buffer, argv[1]) überschrieben und die Zusammenhänge erklärt. Mit einem 2002 aktuellen VS hat das ganze wahrscheinlich auch funktioniert. Zu erwarten, dass Exploits portabel sein sollen, ist vielleicht etwas übertrieben. Michl schrieb: > Der gcc-Doku wird die Verwendung dieses Begriffes aber nachgesehen... Du vergisst dabei, dass es sich hier nicht um die Benutzer-Doku des GCC handelt, sondern um die interne, die sich also an Entwickler richtet, die selbst mit dem GCC arbeiten. Aus Nutzersicht (also aus der des C-Standards) gibt es keine Verpflichtung für einen Stack. Aus Implementierungssicht (Entwickler) haben die meisten (wenn nicht gar alle) Maschinen, auf die GCC portiert ist, sicherlich einen solchen. Übrigens hat Peter da ganz großzügig die Überschrift weggelassen, die über all dem, was er zitiert hat, drüber steht:
Damit ist also völlig klar, dass es Maschinen geben kann, für die diese dort dokumentierten Makros nicht existieren. Back to topic: auch, wenn das Ding auf vielen gängigen Maschinen irgendeinen Teil des Stacks ausgeben wird, was genau will man damit? Ohne exakte Kentniss der Details der jeweiligen Maschine kann man damit rein gar nichts explizit sagen, es ist noch nicht einmal klar, ob beispielsweise die Rückkehradresse der aktuellen Funktion mit in dem angezeigten Datenmüll ist oder nicht.
Gast
#3883106
Jörg Wunsch schrieb: > Back to topic: auch, wenn das Ding auf vielen gängigen Maschinen > irgendeinen Teil des Stacks ausgeben wird, was genau will man damit? Nachschauen, ob der Schadcode, den er eingeschleust hat, auch richtig angekommen ist ;) MfG Klaus
Gast
#3883133
Im Anhang noch der komplette Code, der (zusammen mit einigen Seiten Erklärung, für die sich jeder selbst das Buch zulegen darf) lediglich das Prinzip des Bugs an einem nachvollziehbaren Mickey-Maus-Beispiel erklärt. Die Zielgruppe des Buchs hatte natürlich Windows und VS6.0 und konnte sehr wahrscheinlich die dokumentierten Schritte nachvollziehen, um anhand der Ausgaben das Argument herauszufinden, das nötig ist, um sich selbst zu hacken und bar() aufrufen. Wenn sich hinterher der Leser gemerkt hat, dass sehr seltsame Dinge passieren können, wenn man statische Buffer überlaufen lässt, war das Ziel des Kapitels erreicht; ob der Code mit einem obskuren Compiler auf einer obskuren Rechnerarchitektur unter einem obskuren Betriebssystem auch liefe, war dem Autor natürlich völlig egal. Mark 99 schrieb: > Dennis S. schrieb: >> Da das >> Buch im Microsoft Press-Verlag erschienen ist, > > Das erklärt den Scheiß --> Tonne. Es geht um die Erklärung von Sicherheitslücken und hier speziell Stack Overruns. Selbstverständlich ist das immer systemspezifisch. Nirgends wurde behauptet, daß es sich um ein Buch über ISO C handelt. Ist für dich ein Buch über AVR-Programmierung auch für die Tonne, weil da drin steht, wie man I/O-Ports anspricht und den ADC konfiguriert? Das ist nun mal systemspezifisch. Frank M. schrieb: > So ziemlich alle Architekturen kennen einen Stack. Der wird aber nicht > auf allen Architekturen vollständig für Funktionsargumente benutzt, > siehe SPARC. > >> Der gcc-Doku wird die Verwendung dieses Begriffes aber nachgesehen... > > Du wirfst da was durcheinander: Bei der Sprachdefinition von C braucht > man den Begriff "Stack" tatsächlich nicht. Dieses Buch hat doch gar nicht die Aufgabe, die Sprache C definieren. Tom schrieb: > Im Anhang noch der komplette Code, der (zusammen mit einigen Seiten > Erklärung, für die sich jeder selbst das Buch zulegen darf) lediglich > das Prinzip des Bugs an einem nachvollziehbaren Mickey-Maus-Beispiel > erklärt. Die Zielgruppe des Buchs hatte natürlich Windows und VS6.0 und > konnte sehr wahrscheinlich die dokumentierten Schritte nachvollziehen, > um anhand der Ausgaben das Argument herauszufinden, das nötig ist, um > sich selbst zu hacken und bar() aufrufen. Wenn sich hinterher der Leser > gemerkt hat, dass sehr seltsame Dinge passieren können, wenn man > statische Buffer überlaufen lässt, war das Ziel des Kapitels erreicht; > ob der Code mit einem obskuren Compiler auf einer obskuren > Rechnerarchitektur unter einem obskuren Betriebssystem auch liefe, war > dem Autor natürlich völlig egal. Danke, ich war zu faul das zu schreiben, weil die Diskussion schon so weit vom Kern des Themas entfernt war... Rolf Magnus schrieb: > Dieses Buch hat doch gar nicht die Aufgabe, die Sprache C definieren. Habe ich auch nirgendwo behauptet. Es ging um den "Vorwurf", dass die gcc-Dokumentation sehr wohl von einem Stack plappert, obwohl dieser gar nicht Umfang der Sprache ist. Bitte sorgfältiger lesen. Danke. Tom schrieb: > Im Anhang noch der komplette Code, der (zusammen mit einigen Seiten > Erklärung, für die sich jeder selbst das Buch zulegen darf) lediglich > das Prinzip des Bugs an einem nachvollziehbaren Mickey-Maus-Beispiel > erklärt. Als geschlossenes Beispiel hat das natürlich schon deutlich mehr Sinn, ja. Frank M. schrieb: > Rolf Magnus schrieb: >> Dieses Buch hat doch gar nicht die Aufgabe, die Sprache C definieren. > > Habe ich auch nirgendwo behauptet. Es ging um den "Vorwurf", dass die > gcc-Dokumentation sehr wohl von einem Stack plappert, obwohl dieser gar > nicht Umfang der Sprache ist. Du verteidigst aber oben den Vorwurf gegen das Buch. Zumindest kann man das da rauslesen. > Bitte sorgfältiger lesen. Danke. Bitte sorgfältiger schreiben. Danke. Peter II schrieb: > Jobst Quis schrieb: >> Das funktioniert nur, solange es in der letzten Funktion des Programms >> geschieht. Es holt mehr Argumente vom Stack als vorher draufgelegt >> wurden, die Probleme damit hätten die folgenden Funktionen. > > nein, denn bei cdecl räumt der Aufrufe der Stack wieder auf und diese > kennt ja die Paramter. > > http://de.wikipedia.org/wiki/Aufrufkonvention#stdcall Aber das Aufräumen geschieht nach der Anzahl der Parameter und nicht durch Interpretation des Formatstrings. Bei einem konstanten Formatstring wäre das dem Compiler ja theoretisch noch möglich, aber er muss ja nicht konstant sein. Wenn ich mal bei printf einen Parameter vergesse, kommt prompt ein "Segmentation Fault" oder ähnliches. Und ohne cdecl-Aufrufkonvention wäre eine Funktion mit variabler Parameterzahl garnicht möglich.
Gast
#3884136
Rufus Τ. Firefly schrieb: > Wenn aber die Maschine gar keinen Stack hat, wie Jörgs SPARC? Da wird > dann wohl die ABI anders aussehen, und die Funktion was anderes machen, > bzw. den Begriff "Stack" eher als Metabegriff auslegen. Der Vollständigkeit halber: Bei SPARC werden die ersten 6 Parameter über Register übergeben (%i0 bis %i5 bzw. %o0 bis %o5). Alles was darüber hinausgeht kommt auf den Stack. Aber nicht direkt am Stackpointer (ja, es gibt auch hier einen Stack!), sondern mit ein wenig Abstand (genau sagt kommen dazwischen nochmal unter anderem 16 Words Platz für das Sichern der Registerwindow-Inhalte, für den Fall, dass die Register Windows alle bereits benutzt werden). Alles nachzulesen im SPARC ABI. Wenn nun aber der Code mit -mflat kompiliert wurde, dann sieht die Sache wieder anders aus, da keine Register Windows verwendet werden. Es ist also nicht nur abhängig vom Prozessor sondern auch von den Einstellungen beim Kompilieren und noch einigen anderen Punkten. Kurz gesagt: Es kommt irgendwas raus, einen Sinn macht es nicht unbedingt. meckerziege schrieb: > Der Vollständigkeit halber: Bei SPARC werden die ersten 6 Parameter über > Register übergeben Yep, dass nur die ersten N Parameter in Registern übergeben werden, schrieb ich oben schon. Ich wusste nur nicht mehr aus dem Kopf, wie groß N genau ist. Im Gegensatz beispielsweise zum AVR-GCC passiert das dort auch für variable Argumentlisten. Der AVR-GCC übergibt zwar normalerweise auch viele Parameter in Registern, aber bei varargs verfällt er sofort auf den Stack. Jobst Quis schrieb: > Aber das Aufräumen geschieht nach der Anzahl der Parameter und nicht > durch Interpretation des Formatstrings. Bei einem konstanten > Formatstring wäre das dem Compiler ja theoretisch noch möglich, aber er > muss ja nicht konstant sein. Das wär' ja auch 'ne mittlere Katastrophe. Beim Aufräumen müssen natürlich genau die Parameter wieder runter vom Stack, die vorher draufgelegt wurden (und nicht irgendwelche, die irgendwie im Formatstring stehen). Und wenn der Aufrufer nicht weiß, wieviele und welche Parameter das sind, wer dann? Jörg Wunsch schrieb: > Im Gegensatz beispielsweise zum AVR-GCC passiert das dort auch für > variable Argumentlisten. Der AVR-GCC übergibt zwar normalerweise > auch viele Parameter in Registern, aber bei varargs verfällt er > sofort auf den Stack. Naja, das kann man eben nicht einfach ändern... Johann L. schrieb: > Naja, das kann man eben nicht einfach ändern... Ist mir schon klar. War auch keine Kritik (jenseits von printf und seinen Derivaten braucht man varargs ja ohnehin eher selten), sondern sollte nur beschreiben, dass es da eben auch zwischen den verschiedenen GCC-Plattformen zuweilen krätige Unterschiede gibt. Naja, so unterschiedlich wie ABIs eben sein können. Peter II schrieb: > dann scheint die Doku von GCC aber falsch zu sein. > > https://gcc.gnu.org/onlinedocs/gccint/Varargs.html > — Macro: __builtin_next_arg (lastarg) > This builtin returns the address of the first anonymous stack argument, Das ist nicht aus der GCC-Doku sondern aus den Internals. Je nach ABI können (system)Bibliotheken dies verwenden um stdarg bzw. Hilfsfunktionen dafür etc. zu implementieren. Siehe die zig anderen Targte-Makros und Expander zur stdarg-Implementierung. Das muss schon alles zusammenpassen, einfach blind Features aus den Internals verwenden ist keine gute Idee, z.B. auch für nur intern zu verwendende Constraints. Für den "normalen" Anwender ist dieses Built-in also nicht gedacht und auch nicht in der GCC-Doku bei den Built-ins gelistet. Dennis S. schrieb: > Hallo zusammen, > in dem Buch "Writing Secure Code" habe ich einen Quellcode in der > folgenden Art gefunden: > >
Schmeiss bitte das Buch weg oder verbrenne es! Der printf in "foo()" corrumpiert möglicherweise den Stack und das hat mit "Secure Code" nichts zu tun. Es sei denn dies wäre ein Beispiel wie man nicht programmieren soll...
Gast
#3891548
Eric B. schrieb: > Der printf in "foo()" > corrumpiert möglicherweise den Stack und das hat mit "Secure Code" > nichts zu tun. nein macht er bestimmt nicht, da er nur lesend zugreift. Eric B. schrieb: > Schmeiss bitte das Buch weg oder verbrenne es! Der printf in "foo()" > corrumpiert möglicherweise den Stack und das hat mit "Secure Code" > nichts zu tun. Es sei denn dies wäre ein Beispiel wie man /nicht/ > programmieren soll... Du hast nur die Hälfte mitbekommen... Siehe die schöne Zusammenfassung von Autor: Tom (Gast) Datum: 14.11.2014 11:43 Gruß Dennis
Gast
#3892291
Dennis S. schrieb: > Frage: warum funktioniert das? Hallo Dennis, ich hab den Eindruck, dass Deine eigentliche Frage noch gar nicht richtig beantwortet wurde: Bei variadischen Funktionen (Funktionen mit variabler Anzahl an Argumenten) ist beim Compilieren nicht bekannt bzw. festgelegt, welche und wieviele Daten übergeben werden. Aus diesen Grund werden die Daten in Form einer Liste von "int" übergeben, und diese Liste liegt nicht selten auf dem Stack. Beim Aufruf von
passiert nun folgendes: Der Formatstring sagt aus, daß dem printf 6 Argument übergeben wurden, obwohl in Wirklich kein Argument übergeben wurde. Printf holt sich also die vermeindlichen 6 Argumente vom Stack, und zeigt sie an. Da aber gar keine Argumente übergeben wurde, wird das angezeigt, was vorher schon auf dem Stack gelegen hat. Jenachdem ob da überhaupt etwas liegt, kann es einen Speicherfehler heben. Bronco schrieb: > ich hab den Eindruck, dass Deine eigentliche Frage noch gar nicht > richtig beantwortet wurde: Doch, das ist alles schon gesagt worden. Auch das es in C gar keinen Stack geben muss, von dem sich printf die Werte holt. Bronco schrieb: > Hallo Dennis, > > ich hab den Eindruck, dass Deine eigentliche Frage noch gar nicht > richtig beantwortet wurde: > Bei variadischen Funktionen (Funktionen mit variabler Anzahl an > Argumenten) ist beim Compilieren nicht bekannt bzw. festgelegt, welche > und wieviele Daten übergeben werden. Aus diesen Grund werden die Daten > in Form einer Liste von "int" übergeben, und diese Liste liegt nicht > selten auf dem Stack. > > Beim Aufruf vonprintf("My Stack: \n%p\n%p\n%p\n%p\n%p\n%p\n\n"); > passiert nun folgendes: > Der Formatstring sagt aus, daß dem printf 6 Argument übergeben wurden, > obwohl in Wirklich kein Argument übergeben wurde. > Printf holt sich also die vermeindlichen 6 Argumente vom Stack, und > zeigt sie an. Da aber gar keine Argumente übergeben wurde, wird das > angezeigt, was vorher schon auf dem Stack gelegen hat. > Jenachdem ob da überhaupt etwas liegt, kann es einen Speicherfehler > heben. Mir ist das schon klar gewesen, aber dennoch danke für deine Mühe! :-) Ich hatte mich etwas aus der Diskussion zurückzogen, weil die angesprochenen "Spezialfälle" für mich nicht relevant sind. Gruß Dennis Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|