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.
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.
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:
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.
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.
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.
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.
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.
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?
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...
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.
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:
1
GCC comes with an implementation of <varargs.h> and <stdarg.h> that
2
work without change on machines that pass arguments on the stack. Other
3
machines require their own implementations of varargs, and the two
4
machine independent header files must have conditionals to include it.
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.
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
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.
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.
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...
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
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
1
printf("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.
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