Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]12554[/thread]

Beispiel für die (sichere?) Verwendung von eval

Leser: 2


<< |< 1 2 >| >> 13 Einträge, 2 Seiten
Ronnie
 2008-09-28 12:44
#114996 #114996
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
"eval is evil!" - gehört zu den meist verwendeten Sätzen, wenn man auf eval zu sprechen kommt. Ich möchte mal folgendes kleines Skript zur Diskussion stellen, das ich für einen Freund geschrieben habe um ihm zu zeigen, wie seine C++ Programmieraufgabe in einer Skriptsprache eleganter gelöst werden könnte.
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/perl

use strict;
use warnings;

use Readonly;

Readonly my $SIGN    => qr{[+-]?};
Readonly my $NUMBER  => qr{\d+\.?\d*};
Readonly my $OP      => qr{[\+\-\*\/]};
Readonly my $SPACES  => qr{\s*};
Readonly my $VAL     => qr{ $SPACES ( $SIGN $NUMBER ) $SPACES }x;
Readonly my $EXPR    => qr{
    $SPACES
    ( $SIGN $NUMBER $SPACES $OP $SPACES $SIGN $NUMBER )
    $SPACES
}x;

print "Rechenbeispiel eingeben: ";
my $task = <STDIN>;
chomp($task);

my ($expr, $guessed_value) = $task =~ m{^ $EXPR = $VAL $}x;#
die "unvalid expression!\n" unless $expr;
die "unvalid value!\n"      unless $guessed_value;

my $true_value = eval ($expr);

print $guessed_value == $true_value
      ? "Rechnung ist richtig!\n"
      : "Rechnung ist falsch! Ergebnis ist $true_value\n";

Natürlich hätte es andere Wege gegeben die Aufgabe zu lösen, aber ich finde eval an dieser Stelle einfach, nützlich und sicher. Spricht aus eurer Sicht etwas dagegen?

Gruß,
Ronnie
topeg
 2008-09-28 14:13
#114999 #114999
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Du überprüfst ja, was ausgeführt wird. und ich sehe keine Möglichkeit Code ein zu schleusen.
Gefährlich wir es ja z.B. dann wenn man über Nutzer grenzen hinweg code in eval einführen kann.

Den Code halte ich durchaus für ein sinnvolles Beispiel um eval zu verwenden, da du vorher ausführlich testest.
moritz
 2008-09-28 17:48
#115000 #115000
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Hier kann man statt eval auch CPAN:Math::Expression::Evaluator nehmen und sich um den Sicherheitsaspekt keine Sorgen machen.

(Das Modul hat auch eine Funktion, die einen mathematischen Ausdruck mittels eval() in ein perl-sub kompiliert, aber natürlich nur, wenn die Eingabe vorher erfolgreich geparst wurde.)
Ronnie
 2008-09-28 19:24
#115001 #115001
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Hallo moritz,
moritz+2008-09-28 15:48:17--
Hier kann man statt eval auch CPAN:Math::Expression::Evaluator nehmen und sich um den Sicherheitsaspekt keine Sorgen machen.

das ist ein wirklich schickes Modul, dass ich mir auf jeden Fall gelegentlich im Detail betrachten muss. Danke für die Info!

Gruß,
Ronnie
moritz
 2008-09-28 22:47
#115004 #115004
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Schamlose Eigenwerbung scheint zu funktionieren ;-)
sid burn
 2008-10-07 12:05
#115239 #115239
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
"eval is not evil!" ;)

Als erstes muss man bei Perl sagen welches eval man meint. Leider nutzt Perl ja für Exception fangen ebenfalls eval. Also gegen den Block eval kann man definitiv sagen das dieser nicht evil ist und man ihn sooft verwenden sollte wie es nur geht. Leider wirft Perl ja nicht bei allen Sachen Exceptions und leider immer noch oft genug blöde "undefs" oder andere return Werte zurück um ein Fehler zu Signalisieren.

Ansonsten kann das String eval auch für gute Sachen genutzt werden. Denn man kann damit ja Code zur Laufzeit generieren. Diese Flexibilität kann man dazu nutzen Code wirklich stark abzukürzen oder sogar die Performance eines Programmes erheblich zu steigern. Und wenn man den Code komplett selber generiet ohne Usereingaben zu beinhalten kann dort auch kein Nutzer Code einschleussen oder eine Sicherheitslücke ausnutzen.

Ein zusätzliches Beispiel hierfür von mir ist auch schon fast knapp 2 jahre alt und hier zu finden:
http://forum.ubuntuusers.de/topic/perl:-20fache-la...

Hier nutze ich String Eval und das Programm ist danach fast 20mal schneller. Allerdiengs hätte ich dort auch vorkompilierte Regexe nutzen können (qr//), was ich auch geschrieben habe. Dies wäre auch meine persönliche bevorzugte Variante.


Die Nachteile von String evals und der Codegenerierung sind eher das diese absolut schlecht wartbaren Code erzeugen. Es ist kompliziert nachzuvollziehen was zusammengebaut wird, und es abzuändern.

Und dazu kommt noch das für die meiste Code Generierrung bessere einfachere Möglichkeiten gibt. Dafür hat man ja Typeglobs, Subroutinenreferenzen etc. Sprichwort "Funktionale Programmierung".


So wie du eval genutzt hast würde ich es ehrlich gesagt nicht nutzen. Da auch eine manuelle Überprüfung immer Fehler enthalten kann. Und da du sowieso schon die ganzen Regexe geschrieben hast für die einzelnen Tokens hättest den ganzen String auch mit den Regexoptionen "m//gc" Schrittweise durchgehen können und Parsen können. Wäre auch nicht sehr viel komplexer gewesen.


Mein Fazit ist also das String eval nicht unbedingt evil ist wenn man es zur Code generierung nutzt, allerdiengs sind hier die Möglichkeiten der "Funktionalen Programmierung" besser (im Sinne von flexibilität, wartbarkeit).
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
bloonix
 2008-10-08 11:22
#115262 #115262
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
sid burn+2008-10-07 10:05:15--
"eval is not evil!" ;)

Doch, ist es. Der Spruch hat eine daseins Berechtigung.

eval ... goto ... selbst Perl wird als evil bzw. als schmutzig bezeichnet
und verwunderlich ist das nicht, denn es gibt leider zuviele Entwickler,
die es falsch verwenden.

Code: (dl )
eval <STDIN>;


Da kann eval nichts für, trotzdem ist der Spruch da. Wahrscheinlich
um Entwickler abzuschrecken und um sie zum Nachdenken zu bewegen :-)
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
sid burn
 2008-10-08 12:18
#115265 #115265
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Doch, ist es. Der Spruch hat eine daseins Berechtigung.

Nur teilweise.
Aber das habe ich ja oben genauer erklärt, oder was ist an diesem Stück Code hier "evil"?

Code: (dl )
1
2
3
4
5
6
7
8
eval { 
open my $fh, '<', $file or die $!;
# noch was
close $fh or die $!;
};
if ( $@ ) {
warn "Konnte irgendwas nicht machen!\n"
}


absolut gar nix!
"eval is evil!" solche Sprüche führen nur dazu das die meisten Leute eval sofort meiden auch für das wofür es gut einsetzbar ist ohne sich evtl. damit beschäftigt zu haben. Ein "eval can be evil!" würde passender sein. ;)

Quote
eval ... goto ... selbst Perl wird als evil bzw. als schmutzig bezeichnet

goto kann man auch Klasse verwenden.

Code: (dl )
goto &subroutine;

Ist vorallem da nützlich wenn man eine Subroutine erstellt, und die aktuelle Subroutine in caller() nicht auftauchen soll. Oder bei Endrekursion.

Quote
eval ... goto ... selbst Perl wird als evil bzw. als schmutzig bezeichnet

Und deswegen sollte man Perl nicht mehr nutzen oder was möchtest du sagen?

CGI (Perl) ist sowieso veraltet und wurde durch PHP ersetzt?

Solche Sprüche und allgemeine Aussagen machen eher mehr kaputt als das Sie irgendwem helfen. ;)

Quote
und verwunderlich ist das nicht, denn es gibt leider zuviele Entwickler, die es falsch verwenden.

Was für mich keine Begründung ist. ;)
Viele Coden mit Perl unleserlich oder können es nicht. Es gibt nen Haufen Sprüche deswegen gegen Perl. Deswegen kein Perl nutzen weil es manche Entwickler nicht können oder es "falsch" verwenden? Solche Aussagen kommen eher von Leute die sich meist nicht mit der Materie auseinandergesetzt haben.

Wie oft habe ich schon in anderen Foren über Perl Diskutiert. Eine Aussage von mir "Perl ist auch ganz gut für Webentwicklung" wird dann mit "Perl ist doch veraltete Programmierung, wer nutzt das schon noch?" zurückgeschlagen und wenn man dann sagt. Hey nimm nen Framework "Catalyst, Jifty,..." kommt dann nur zurück "Was für Perl gibt es Webframeworks?" Und von solchen Leuten kommen dann immer so intelligente Sprüche und halten sich dann auch an solche Sprüche. ;)

Ich will nicht Wissen wieviele Leute lieber mit Python Programmieren weil Sie über Perl gehört haben das es unsauber nicht wartbar, keine OOP besitzt und sowieso nur für CGI brauchbar ist. Überhaupt ist Perl ja == CGI, und ich wurde sogar schonmal Persönlich gefragt wie ich Python finde da er gelesen hätte das Python der Nachfolger von Perl wäre...

Um zum Ausgangspunkt zurück zu kommen. Solche Meinungen verbreiten sich über genau die selben Sprüche wie solche wie "eval is evil!".

Es dient als Abschreckung, oft klappt dies, und genau das bewegt dazu eben nicht darüber nachzudenken. Den wie du ja sagst solch einen Spruch scheint es anscheind ja nicht umsonst zu geben. Und Leute nehmen sowas dann gerne als bare Münze.

Quote
Da kann eval nichts für, trotzdem ist der Spruch da. Wahrscheinlich
um Entwickler abzuschrecken und um sie zum Nachdenken zu bewegen :-)

Genau "eval" kann nichts dafür das es falsch verwendet wird. Deswegen ist es ja auch nicht evil. ;) Höchstens der Programmierer ist evil. ;) C++, Visual Basic etc. ist ja auch nicht evil nur weil dadrin vielleicht 90% aller Viren Programmiert werden.

Schlußendlich liegt es immer an PEBKAC.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
bloonix
 2008-10-08 12:43
#115266 #115266
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
</roman>
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
pq
 2008-10-08 13:26
#115268 #115268
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
die krux ist, dass eval 2 funktionitäten hat, string-eval (für mich das eigentliche eval) und
block-eval, so eine art try(). da die beiden eigentlich nichts miteinander zu tun haben,
sollte man sie getrennt bewerten.
string-eval ist meiner meinung nach genauso evil wie symbolische referenzen. das heisst,
ich rate allen, die danach fragen, davon ab. erst wenn man sich genug auskennt, kann man
selbst abschätzen, in welchen (seltenen) fällen es vielleicht doch sinnvoll sein kann.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
<< |< 1 2 >| >> 13 Einträge, 2 Seiten



View all threads created 2008-09-28 12:44.