46 Stimmen

Warum sollten exec() und eval() vermieden werden?

Ich habe das schon mehrfach an verschiedenen Stellen gesehen, aber nie eine befriedigende Erklärung dafür gefunden, warum das so sein sollte.

Deshalb wird hier hoffentlich eine vorgestellt werden. Warum sollten wir (zumindest im Allgemeinen) nicht exec() y eval() ?

EDIT: Ich sehe, dass die Leute davon ausgehen, dass sich diese Frage auf Webserver bezieht - das tut sie nicht. Ich kann verstehen, warum eine nicht sanitisierte Zeichenkette, die an exec könnte schlecht sein. Ist es schlecht in Nicht-Web-Anwendungen?

1 Stimmen

Können Sie einige Zitate von "mehreren Stellen" anführen, um zu klären, auf welche Bemerkungen Sie sich stützen? Es ist wichtig zu wissen, was Sie gelesen haben, um zu dem Schluss zu kommen, dass sie gemieden werden sollten. Das ist kein einfaches Thema, und Sie müssen Ihre Informationsquelle angeben, um Ihre Frage zu klären.

0 Stimmen

Soweit ich mich erinnere (da ich diese Orte im Laufe der Jahre nicht mit Lesezeichen versehen habe), haben die Warnungen in der Regel die Form von "Natürlich könnten wir eval() um dieses Problem zu lösen, aber das wäre unanständig."

0 Stimmen

Das jüngste Beispiel war wohl die Verwendung von exec() als Mittel zum Kontrollfluss innerhalb des Programms.

32voto

RossFabricant Punkte 11872

Oft gibt es klarere, direktere Wege, um die gleiche Wirkung zu erzielen. Wenn Sie eine komplexe Zeichenkette erstellen und sie an exec übergeben, ist der Code schwer zu verstehen und schwer zu testen.

Beispiel: Ich habe einen Code geschrieben, der String-Schlüssel und -Werte einliest und entsprechende Felder in einem Objekt setzt. Das sah wie folgt aus:

for key, val in values:
    fieldName = valueToFieldName[key]
    fieldType = fieldNameToType[fieldName]
    if fieldType is int:
        s = 'object.%s = int(%s)' % (fieldName, fieldType) 
    #Many clauses like this...

exec(s)

Dieser Code ist für einfache Fälle nicht allzu schlimm, aber mit dem Auftauchen neuer Typen wurde er immer komplexer. Wenn es Bugs gab, wurden sie immer beim Aufruf von exec ausgelöst, so dass Stack Traces mir nicht halfen, sie zu finden. Schließlich bin ich zu einer etwas längeren, weniger cleveren Version übergegangen, die jedes Feld explizit setzt.

Die erste Regel zur Klarheit des Codes lautet, dass jede Zeile Ihres Codes leicht zu verstehen sein sollte, wenn man nur die benachbarten Zeilen betrachtet. Aus diesem Grund wird von goto und globalen Variablen abgeraten. exec und eval machen es leicht, diese Regel zu verletzen.

4 Stimmen

Strohmann-Argument, man sollte gar nicht erst so weit kommen, dass man bauen eine Zeichenkette, die an exec übergeben wird. Die Übergabe eines Literals ist schon schlimm genug. Ist es nicht noch schlimmer, exec zu verwenden, wenn man es gar nicht braucht? setattr würde die Aufgabe besser erfüllen. Sie sind jedoch nicht so erfahren mit Python; fieldType is int ? und (int)%s ??

19 Stimmen

Es handelt sich nicht um einen Strohmann. Welchen Sinn hat es, eine wörtliche Rede zu halten? Was Ihre anderen Kommentare betrifft. Ich habe einen kurzen Code zur Veranschaulichung eingegeben, in der Hoffnung, dass er meinen Standpunkt verdeutlicht, und es wäre leicht zu erkennen, wie ein solcher Fall komplexer werden könnte. Es stimmt, dass meine Python-Kenntnisse ein wenig eingerostet sind, aber das hat wenig Einfluss auf den Punkt, den ich machen wollte.

0 Stimmen

Zum Vergleich: Die explizitere Art, die s = Zeile ist setattr(object, fieldName, int(fieldType))

17voto

bobince Punkte 512550

Wenn Sie exec und eval brauchen, ja, dann brauchen Sie sie wirklich.

Der Großteil der Verwendung dieser Funktionen (und ähnlicher Konstrukte in anderen Skriptsprachen) in der freien Wildbahn ist jedoch völlig unangemessen und könnte durch andere, einfachere Konstrukte ersetzt werden, die schneller und sicherer sind und weniger Bugs aufweisen.

Sie kann mit korrektem Escaping und Filterung, sichere Verwendung von exec und eval. Aber die Art von Programmierer, die direkt auf exec/eval zurückgreift, um ein Problem zu lösen (weil sie die anderen Möglichkeiten, die die Sprache zur Verfügung stellt, nicht verstehen), ist nicht die Art von Programmierer, die in der Lage sein wird, diese Verarbeitung richtig hinzubekommen; es wird jemand sein, der die String-Verarbeitung nicht versteht und einfach blind Teilstrings verkettet, was zu fragilem, unsicherem Code führt.

Das ist die Verlockung der Strings. Das Herumwerfen von Saitensegmenten siehe einfach und gaukelt naiven Programmierern vor, dass sie wissen, was sie tun. Aber die Erfahrung zeigt, dass die Ergebnisse fast immer in irgendeiner Ecke (oder auch nicht) falsch sind, oft mit potenziellen Sicherheitsauswirkungen. Deshalb sagen wir, eval ist böse. Deshalb sagen wir, dass regex-for-HTML böse ist. Aus diesem Grund fordern wir die SQL-Parametrisierung. Ja, Sie kann all diese Dinge bei der manuellen Verarbeitung von Zeichenketten richtig zu machen... aber wenn Sie nicht bereits verstehen, warum wir diese Dinge sagen, stehen die Chancen gut, dass Sie wird nicht .

12voto

Eli Bendersky Punkte 246100

Sicherheit beiseite, eval y exec werden aufgrund der Komplexität, die sie verursachen, oft als unerwünscht eingestuft. Wenn Sie eine eval Aufforderung weiß man oft nicht, was wirklich dahinter steckt, weil sie auf Daten wirkt, die normalerweise in einer Variablen enthalten sind. Das macht den Code schwieriger zu lesen.

Die volle Leistung des Dolmetschers in Anspruch zu nehmen, ist eine schwere Waffe, die nur für sehr heikle Fälle reserviert werden sollte. In den meisten Fällen ist es jedoch besser, dies zu vermeiden und einfachere Werkzeuge zu verwenden.

Wie bei allen Verallgemeinerungen ist jedoch auch hier Vorsicht geboten. In einigen Fällen können exec und eval nützlich sein. Aber Sie müssen einen sehr guten Grund haben, sie zu verwenden. Siehe ce poste für eine zulässige Verwendung.

0 Stimmen

Es sieht so aus, als ob eine Antwort ausgewählt wurde, die hat nicht verwenden. exec() ... gibt es Fälle, in denen exec() o eval() notwendig/nicht unvernünftig sind?

0 Stimmen

Antwort abgelehnt. Abgesehen von der Sicherheit sehen eval und exec wie Wartungsalpträume aus.

0 Stimmen

@Isaac, die Antwort wurde ausgewählt, weil ich nach Möglichkeiten gesucht habe, die Aufgabe ohne exec zu erledigen. Im allgemeinen Fall war es eine gute Verwendung für exec, die ich schließlich verwendete, als die Methoden willkürlicher wurden

12voto

Square Rig Master Punkte 658

eval() y exec() kann eine faule Programmierung fördern. Noch wichtiger ist, dass der Code, der ausgeführt wird, möglicherweise nicht zur Entwurfszeit geschrieben und daher nicht getestet wurde. Mit anderen Worten: Wie testet man dynamisch generierten Code? Vor allem in verschiedenen Browsern.

3 Stimmen

+1: Die "Grundlegende Erwartung" ist, dass Sie den gesamten Quelltext haben. Mit exec() und eval() haben Sie - trivialerweise - nicht alle die Quelle.

10voto

zzzeek Punkte 66340

Im Gegensatz zu dem, was die meisten Antworten hier sagen, ist exec tatsächlich Teil des Rezepts, um super-komplette Dekoratoren in Python zu bauen, da man alles über die dekorierte Funktion genau duplizieren kann, was die gleiche Signatur für die Zwecke der Dokumentation und so weiter erzeugt. Es ist der Schlüssel für die Funktionalität des weit verbreiteten Dekorator-Moduls ( http://pypi.python.org/pypi/decorator/ ). Andere Fälle, in denen exec/eval unverzichtbar sind, sind die Erstellung von Anwendungen mit "interpretiertem Python", wie z. B. eine in Python geparste Template-Sprache (wie Mako oder Jinja).

Es ist also nicht so, dass das Vorhandensein dieser Funktionen ein unmittelbares Zeichen für eine "unsichere" Anwendung oder Bibliothek ist. Mit ihnen in der naiven javascripty Weg zu bewerten eingehende JSON oder etwas, ja, das ist sehr unsicher. Aber wie immer kommt es auf die Art und Weise an, wie man sie benutzt, und diese Funktionen sind sehr wichtig.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X