exit in subroutine - kein guter programmierstil
dennis
- cgi
hallo,
ich ich habe vorhin gelesen das man exit in subroutinen nicht verwenden soll weil es kein guter programmierstil ist. man soll lieber ein return-anweisung in der subroutine haben und dann den exit befehl irgenwo anders ausführen.
wie soll den sowas aus sehen?
kann mir des bitte einer erklären?
1000 dank im voraus
Halihallo dennis
ich ich habe vorhin gelesen das man exit in subroutinen nicht verwenden soll weil es kein guter programmierstil ist. man soll lieber ein return-anweisung in der subroutine haben und dann den exit befehl irgenwo anders ausführen.
exit sollte sowieso nur in der Shell für die Interaktion mit anderen Programmen
verwendet werden, ansonsten ist "die" oder "croak" wohl sinnvoller, sodass man auch
weiss, woran das Programm gestorben ist.
wie soll den sowas aus sehen?
sub test_it {
return 0 unless (-e 'test.txt'); # tja, wenn die Datei nicht existiert, stirb!
open( F, '<./test.txt' ) || return 0;
# do something with F
close(F) || return 0;
return 1;
}
exit(test_it());
Wenn ein Programm nun dieses startet, wird es über den Exit-Code über den (Miss-)Erfolg
informiert (entweder Exit-Code 0 oder 1).
PS: Ich hoffe du hast Perl gemeint, ansonsten walte der Analogie. In beiden Fällen jedoch
schreib die verwendete Programmiersprache an.
Viele Grüsse
Philipp
Hi Philipp,
exit sollte sowieso nur in der Shell für die Interaktion mit anderen Programmen
verwendet werden, ansonsten ist "die" oder "croak" wohl sinnvoller, sodass man auch
weiss, woran das Programm gestorben ist.
Kannst du mir als Laien mal verständlich erklären, was es mit "croak" auf sich hat? Aus der perldoc bin ich nicht so recht schlau geworden.
sub test_it {
[...]
Worin liegen der Unterschied und der Vorteil in der sub test_it gegenüber der Variante, innerhalb der sub gleich exit(0) oder exit(1) auszuführen? Bestehen da Bedenken hinsichtlich des Programmierstils oder hinsichtlich der Ausführung des Scriptes oder beides oder was ganz anderes?
Viele Grüße
Torsten
Halihallo Torsten
exit sollte sowieso nur in der Shell für die Interaktion mit anderen Programmen
verwendet werden, ansonsten ist "die" oder "croak" wohl sinnvoller, sodass man auch
weiss, woran das Programm gestorben ist.
Kannst du mir als Laien mal verständlich erklären, was es mit "croak" auf sich hat? Aus der perldoc bin ich nicht so recht schlau geworden.
use Carp;
croak 'test';
croak und cluck/carp haben dieselbe Funktion wie "die" bzw. "warn", nur, dass die und
warn die aktuelle Position im Programm ausgeben, wo der Fehler genau aufgetaucht ist,
wohingegen cluck/carp/... diejenigen Positionen des "caller" zurückgeben, der die
Funktion wo der Fehler auftritt aufgerufen hat.
Sollte eigentlich in allen Modulen zum Einsatz kommen, denn die Position innerhalb des
Moduls ist oftmals wirklich völlig irrelevant, viel wichtiger wäre es zu wissen, wo der
Fehler im _eigenen_ Programm auftaucht. Man geht hier davon aus, dass das verwendete
Modul "keine Fehler" hat und das der Programmierer im eigenen Programm etwas falsch
gemacht hat. Wichtig ist also alleine zu wissen, wo der Fehler im _eigenen_ Programm
entsteht und genau diese Position wird von croak/carp/cluck/... angegeben.
Worin liegen der Unterschied und der Vorteil in der sub test_it gegenüber der Variante, innerhalb der sub gleich exit(0) oder exit(1) auszuführen? Bestehen da Bedenken hinsichtlich des Programmierstils oder hinsichtlich der Ausführung des Scriptes oder beides oder was ganz anderes?
Es ist einfach unschön, das Programm in einer Schleife oder Prozedur zu beenden. Eine
Prozedur ist eine "atomare" Verarbeitungsvorschrift und Atome soll man bekanntlich nicht
spalten (exit zwischen drin), sonst fliegt einem das Haus um den Kopf :-)
Der Aufbau des Programmes ist einfach schön hierarchisch aufgebaut und dies íst schönes
Programmieren. Man könnte dies mit dem "goto"-Paradigma vergleichen: Das Umherspringen
wird heute als schlechter Programmierstil gewertet, da der Programmfluss einfach sehr
schwer nachzuvollziehen ist. Ähnlich ist es mit exit in Prozeduren.
Oder anders: Eine Prozedur oder besser: eine Funktion gibt einen Wert zurück. Nach einer
Funktion soll entweder weitergearbeitet werden, oder nicht (exit). Aber: Diese
Entscheidung darf nicht bei der Funktion selber liegen, sondern vom äusseren
Programmkontext. Ein anderes Programm braucht vielleicht dieselbe Funktion und will
bei einem Fehler weiterarbeiten, ein exit wäre hier in der Funktion fatal. Wann ein
Programm beendet wird ist von der Aufgabenstellung abhängig, nicht von einer Funktion.
Demnach soll das Hauptprogramm entscheiden, wann schluss ist.
Viele Grüsse
Philipp
Halihallo Torsten
use Carp;
croak 'test';
Einleuchtendes Beispiel:
in einem Modul hat man stehen:
sub new {
my ($class,@params) = @_;
croak('You must pass at least 2 parameters.') if (@params<2);
}
was bringt es dir, wenn die Linie im Modul selber genannt wird (was mit die/warn
geschenen würde)? - Gar nichts, wichtiger wäre es zu wissen, wo du die Methode new in
_deinem_ Programm ohne die nötigen zwei Parameter aufgerufen hast.
Viele Grüsse
Philipp
Hi Philipp,
[...]
was bringt es dir, wenn die Linie im Modul selber genannt wird (was mit die/warn
geschenen würde)? - Gar nichts, wichtiger wäre es zu wissen, wo du die Methode new in
_deinem_ Programm ohne die nötigen zwei Parameter aufgerufen hast.
Die Frage die sich mir jetzt noch stellt ist, wohin schreibt croak die Meldung standardmäßig? In die vordefinierte error-Datei oder wie "die" an STDERR? Oder vielleicht ganz woanders hin?
Viele Grüße
Torsten
Halihallo Siechfred
Die Frage die sich mir jetzt noch stellt ist, wohin schreibt croak die Meldung standardmäßig? In die vordefinierte error-Datei oder wie "die" an STDERR? Oder vielleicht ganz woanders hin?
Da croak gleich funktioniert wie "die", wird die Meldung ausserhalb eval an STDERR
gesendet (sonst natürlich $@).
s. auch Modul-Code von Carp:
sub croak { die shortmess @_ }
sub confess { die longmess @_ }
sub carp { warn shortmess @_ }
sub cluck { warn longmess @_ }
shortmess ruft dann Carp::Heavy auf, wo die caller-Informationen gesammelt werden. Aber
sterben tut das Programm immer noch mit "die" und funktioniert somit "gleich".
Viele Grüsse
Philipp
Hi Philipp,
sub croak { die shortmess @_ }
sub confess { die longmess @_ }
sub carp { warn shortmess @_ }
sub cluck { warn longmess @_ }
Danke für deine Hinweise und deine Geduld :-)
Viele Grüße
Torsten
Halihallo Torsten
Danke für deine Hinweise und deine Geduld :-)
Ist sehr gerne geschehen! ;)
Viele Grüsse
Philipp
Hallo,
die option #!/usr/bin/perl -Tw
ist auch zu empfehlen für gut programierte perl scripts.
Gruss vom Alain
Hi Alain,
die option #!/usr/bin/perl -Tw
ist auch zu empfehlen für gut programierte perl scripts.
Ich halte dein Tainted Modus nicht für so wichtig. Er kann, in manchen Anwendungen nützlich sein, aber meiner Meinung nach nur in rel. wenigen. Wenn man richtig mit Eingaben umgeht, sollte man sowieso kein Problem mit den Sachen, die der Tainted-Mode regelt, haben.
Viel wichtiger ist das meiner Meinung nach, dass "strict" genutzt wird.
Grüße Andres Freund
Halihallo Andres
die option #!/usr/bin/perl -Tw
ist auch zu empfehlen für gut programierte perl scripts.
Ich halte dein Tainted Modus nicht für so wichtig. Er kann, in manchen Anwendungen nützlich sein, aber meiner Meinung nach nur in rel. wenigen. Wenn man richtig mit Eingaben umgeht, sollte man sowieso kein Problem mit den Sachen, die der Tainted-Mode regelt, haben.
Natürlich kann man über eine saubere Programmierung den Tainted-Modus "ersetzen", aber
er bezweckt genau die Qualitätssicherung, dass man eben wirklich sauber programmiert
und nicht etwas vergisst.
sauber verstehe ich hier übrigens als "sicher".
Viel wichtiger ist das meiner Meinung nach, dass "strict" genutzt wird.
IMHO absolut richtig!
Zum tainted-Modus will ich noch anfügen:
Er gehört - wie exit - eher in den Bereich Serveradministration und Multiuserbetrieb
wie z.B. in einem Netzwerk. Auf einem Webserver, wo nur Administratoren und andere
"ausgewählte" Personen Zugriff auf den Server haben, ist der Tainted-Modus eher weniger
relevant. Hier lauert die Gefahr nicht "von innen", sondern "von aussen"; Stichwort
Formulardaten überprüfen. Falls ein Cracker Zugriff auf den Computer "von innen" kriegt
und sich über Exploits und "nicht tainted-sichere Scripte" root-access (oder alles
andere, was man als "böse" oder beunruhigend empfindet) erhascht ist's eh schon viel zu
spät... Nun ja, Sicherheit habe ich hier etwas streng aufgefasst, es geht bei tainted-mod
auch darum, dass die Parameter auf syntaktische Korrektheit überprüft werden und z.B.
nicht gewollte pipes oder Zugriff auf fremde Verzeichnisse verhindert werden, wenn diese
nicht Teil der Aufgabenstellung sind (womit wir auch wieder bei der Formularüberprüfung
wären).
Ich schätze mal, dass man nicht umbedingt einen tainted-Modus für Formularüberprüfungen
haben muss? - Aber für die Administration und Multiuserbetrieb allemal!
Viele Grüsse
Philipp
Hallihallo Philipp,
sauber verstehe ich hier übrigens als "sicher".
Ich indirekt auch. Man kann auch mit dem tainted-Modus ohne Probleme unsichere Scripte schreiben, nur ist es schwerer.
Ähnlich ist es meiner Meinung nach mit dem "sauberen" Scripten. Wenn ein Script übersichtlich ist, wird das sichere Programm auch nicht automatisch hergestellt, sondern das herstellen eines sicheren Programmes erleichtert. Man kann, wie dir auch sicher klar ist, auch mit einem unsauberen/unübersichtlichen Stil ein sicheres Programm schreiben.
Zum tainted-Modus will ich noch anfügen:
Er gehört - wie exit - eher in den Bereich Serveradministration und Multiuserbetrieb
Warum? Ich sehe hier keinen Grund. Die Gefahr, in einem Script z.B. eine Pipe zu öffnen, existiert meiner Meinung nach, sowohl lokal als über ein Script, auch wenn das entdecken und ausnutzen lokal sicherlich leichter ist.
Im Normalfall, wir lassen jetzt mal setuid scripte etc. weg, läuft ein script sowieso mit den berechtigungen des users. Da kann er, solange er nicht Administrator ist, nur sich selber schaden zufügen. Ein Admin sollte aber meiner Meinung nach wissen, was er macht.
Die Gefahr besteht also hauptsächlich bei Programmen, die nicht mit den Rechten des nutzenden Users laufen. Also über setuid sudo oder ähnliche Funktionen mit mehr Rechten als gewöhnlich ausgestattete Scripte.
Viele Grüße,
Andres
Halihallo Andres und Alain
Ich verstehe beide Argumentationen und versuche eine kleine Zusammenfassung meines
derzeitigen Point-of-Views:
Besonders möchte ich noch 5) betonen. Auch wenn -T einige Probleme identifiziert, in
speziellen Programmen für spezielle Anwendungen und -bereiche (z.B. Webumfeld), lauern
spezielle Gefahren, die eben _nicht_ abgedeckt werden. Und genau diese speziellen
Gefahren sind of diejenigen, welche ausgenutzt werden. Zuerst sollte man sich also
mit den wirklich relevanten Problemen/Gefahren beschäftigen (und dies ist leider nicht
immer konform mit der "Meinung" vom Tainted-Modus).
Was meint Ihr (Andres, Alain und andere Forumer)?
Viele Grüsse
Philipp
Hallo Phillipp,
Besonders möchte ich noch 5) betonen. Auch wenn -T einige Probleme identifiziert, in
speziellen Programmen für spezielle Anwendungen und -bereiche (z.B. Webumfeld), lauern
spezielle Gefahren, die eben _nicht_ abgedeckt werden. Und genau diese speziellen
Gefahren sind of diejenigen, welche ausgenutzt werden. Zuerst sollte man sich also
mit den wirklich relevanten Problemen/Gefahren beschäftigen (und dies ist leider nicht
immer konform mit der "Meinung" vom Tainted-Modus).Was meint Ihr (Andres, Alain und andere Forumer)?
danke für die Ausführung,
ich weiss der taint modus ist keine garantie gegen attacks und oder für die sicherheit,
desshalb wärs gut mal konkret zu erfahren (vielleicht in deutsch)
welche gefahren genau z.B. lauern könnten (mit Beispielen).
Ich weiss diverse methoden um selbst unsichere cgi's sicher ausführen zu lassen z.B. ein formular
dass nur über den eigenen server ausführbar sein darf (referer check) wäre eine art,aber selbst da könnte man zwar
den server crushen,da wär dann der taint modus schon gut um diese gefahr zu verhindern.
Dazu was sicherheiten bei perl oder cgis betrifft, hab ich eine sehr gute seite http://www.w3.org/Security/faq/wwwsf4.html
gefunden die das problem sehr detailiert und ausführlich beschreibt,aber leider in englisch.
Beste
Grüsse vom Alain
Hi Philipp und Alain,
ich weiss der taint modus ist keine garantie gegen attacks und oder für die sicherheit,
desshalb wärs gut mal konkret zu erfahren (vielleicht in deutsch)
welche gefahren genau z.B. lauern könnten (mit Beispielen).
Vielleicht hilft dir ja der Artikel von Xwolf:http://www.xwolf.de/artikel/cgisec.shtml
Ich weiss diverse methoden um selbst unsichere cgi's sicher ausführen zu lassen z.B. ein formular
dass nur über den eigenen server ausführbar sein darf (referer check) wäre eine art,aber selbst da könnte man zwar
den server crushen,da wär dann der taint modus schon gut um diese gefahr zu verhindern.
Der Referer bringt rein gar nichts! Den kann jeder Nutzer ohne Probleme fälschen. Daher ist das nur vorgetäuschte Sicherheit. Genauso wie der Tainted-Mode meiner Meinung nach. Ich habe es jezt nicht ausprobiert, aber eigentlich dürften die Parameter nicht einmal vom Tainted-Mode betroffen sein, da sie, um extrahiert zu werden, schon mit einem Regex "behandelt" wurden und daher nicht mehr vom Tainted-Modus betroffen sind.
Was meinst du eigentlich mit "Server crushen"?
Grüße Andres Freund
Hallo,
Was meinst du eigentlich mit "Server crushen"?
ja z.B. daten löschen über ein cgi,die der server eigentlich nicht sollte,die schlussendlich den server zum lahmlegen bringt.
Aber nochmals zum taint modus:
Der taint modus hat schon was ,sonst wär der ja für die katz.Ich hab selber schon
probiert über mein formular username/password eine eingabe so "?username" zu schreiben,was der server mit einem
500er error abweist,durch den taint modus,ohne dass ich eigentlich im perl.cgi geschrieben habe welche eingaben erlaubt sein dürfen oder nicht.
Von daher finde ich Taint schon sehr wirkungs voll.
Gruss vom Alain
Hi Alain,
Ich hab selber schon probiert über mein formular username/password eine eingabe so "?username" zu schreiben,was der server mit einem 500er error abweist,durch den taint modus,ohne dass ich eigentlich im perl.cgi geschrieben habe welche eingaben erlaubt sein dürfen oder nicht.
Aber woher soll der Tainted-Modus wissen, ob das Fragezeichen nicht vielleicht zugelassen ist? Hier sollte man imho ansetzen und diesen Modus wirklich nur zum Testen nutzen.
Viele Grüße
Torsten
Hi Philipp,
- Der Tainted-Modus ist lediglich ein Verfahren, um mögliche Sicherheitslöcher zu
identifizieren, lösen muss es jedoch der Programmierer (durch finden einer geeigneten
RegExp oder anderer Überprüfung).
Eben. So, wie ich es verstanden habe, _zwingt_ der Tainted-Modus den Programmierer lediglich dazu, jedes _mögliche_ Sicherheitsloch zu stopfen. Insoweit bietet er den Schutz, dass er auf das Fehlen geeigneter Schutzmechanismen hinweist, nicht mehr und nicht weniger. Was der Programmierer daraus macht, ist sein Bier, er kann ja auch einfach das -T in der shebang weglassen. BTW, war der Erfinder von Perl eigentlich Frauenfeind, guck mal spaßeshalber hier: http://dict.leo.org/?p=/37m..&search=bang ;-)
- Im Webumfeld lauern ganz andere Gefahren, die mit Tainted-Modus _nicht_ identifiziert
werden, somit halte ich dort ein -T für overkill in dem Sinne, dass man viel schreiben
muss, um -T zufriedenzustellen, was primär gar kein Sicherheitsproblem ist [...]
Ich werde es persönlich mit dem -T genauso wie mit dem -w halten. Zum Testen gut, wenn das Script dann läuft, aus der shebang löschen.
- Fazit II: Beide Verfahren dienen der Identifikation gewisser möglicher
Probleme/Aspekte, gelöst werden müssen sie jedoch immer noch vom Programmierer.
Full ACK.
Besonders möchte ich noch 5) betonen. Auch wenn -T einige Probleme identifiziert, in
speziellen Programmen für spezielle Anwendungen und -bereiche (z.B. Webumfeld), lauern
spezielle Gefahren, die eben _nicht_ abgedeckt werden. Und genau diese speziellen
Gefahren sind of diejenigen, welche ausgenutzt werden. Zuerst sollte man sich also
mit den wirklich relevanten Problemen/Gefahren beschäftigen (und dies ist leider nicht
immer konform mit der "Meinung" vom Tainted-Modus).
Zumindest sollte man sich von einem im Tainted-Modus funktionierenden Script nicht zu der Annahme verleiten lassen, das Script sei sicher. Es ist eben "nur" sicherer.
Viele Grüße
Torsten
Hallo,
die option #!/usr/bin/perl -Tw
ist auch zu empfehlen für gut programierte perl scripts.
Ich halte dein Tainted Modus nicht für so wichtig. Er kann, in manchen Anwendungen
so dann lies mal http://gunther.web66.com/FAQS/taintmode.html#clear_taint
oder http://www.perl.com/pub/a/2002/02/20/css.html
Gruss vom Alain
hi,
ich ich habe vorhin gelesen das man exit in subroutinen nicht verwenden soll weil es kein guter programmierstil ist. man soll lieber ein return-anweisung in der subroutine haben und dann den exit befehl irgenwo anders ausführen.
jow, da ist was dran, schau mal
http://i-netlab.de/cgi-bin/index.cgi?display=4.1
das beschreibt eine Kontrollstruktur wie ich sie in jedem meiner CGIs verwende. Danach kommt immer ein exit() was das Programm beendet, auch wenn es sich an diser Stelle von selbst beenden würde - diese Strukturierung hilft beim Debuggen, deshalb die exit() Notation.
Grundsätzlich sollte jede SubFunktion mit einem return() abgeschlossen werden, auch wenn diese sich nach getaner Arbeit selbst beenden würde. Und Wieder hilft die return() Notation bei etwaigen Fehlern die es manchmal gibt. Also lass ich das return() dort stehen.
Ergo: exit() und return() - damit hat sichs ggf. wie mit den Kommentaren.
Rolf
PS: Bei meinem Streichholzspiel gehe ich manchmal mit exit() aus einer Unterfunktion raus. Du kannst das herausbekommen indem du in den HTML Quelltext schaust: da fehlt manchmal das </body></html> - insofern isses nicht ganz sauber, aber was solls ;-)