2013-05-23 2 views
7

Wir wissen, Python eval() Übel istWie sicher ist SymPys sympify (<string>) .evalf()?

http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html

und Fäden im gesamten Stackoverflow vorschlagen SymPy die evalf() zu verwenden.

Als Python-Neuling kann ich mich nicht wirklich davon überzeugen, dass evalf() sicher ist, da mir die Fähigkeiten fehlen. Kann jemand näher erläutern, was evalf() (anders) tut?

+0

Es gibt keine Vorschläge, 'evalf' anstelle von' eval' zu verwenden, da sie nichts gemeinsam haben. Es gibt Vorschläge, um 'sympify' anstelle von' eval' zu verwenden, aber (aus Sicherheitsgründen) sind sie fehlgeleitet, da diese im Grunde die gleichen sind. – Krastanov

Antwort

7

Es gibt nichts Gemeinsames zwischen Python eval und sympy evalf (letzteres ist für den numerischen Wert von sympy Ausdrucksbäume zu berechnen und es hat nichts mit Parsing zu tun, während eval dreht sich alles um einen String Parsen und Auswerten als wenn es Code ist).

Auf der anderen Seite ist sympify genauso gefährlich wie eval, weil es tatsächlich eval verwendet.

Es gibt zwei grundlegende Modi, in denen sympify verwendet wird, und wahrscheinlich ist es eine schlechte Idee, dass sie in der gleichen Funktion gemischt wurden:

  • sympify(some_object) zurückkehren würde eine Darstellung des Objekts besser geeignet für den Einsatz in ein CAS, wie int(1) in sympy.Integer(1)

  • sympify("some_text") verwandeln würde den Text fast direkt über eval (Suche nach dem Import von sympy.parsing inanalysiertund folge ihm). Es ist sicherer, da es einige Einschränkungen gibt, aber es ist nicht sicher.

+0

Vielen Dank für Ihre Antwort. Könntest du bitte den zweiten Grundmodus erklären, '' sympify ("irgendein Text"), und wie könnte dies böswillig ausgenutzt werden? Zum Beispiel, funktioniert das [Ned Batchelder eval gefährlich] (http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html) Beispiel in SymPy? EG mit 'f = sympy.sympify ('__ import __ (" os ")') gibt mir kein aufrufbares Objekt. –

+2

OK, ich konnte mit 'sympy 'auf' subprocess.Popen' zugreifen und einen Systembefehl ausführen, EG 'f = sympy.sympify (" "[] .__ class __.__ base __.__ subclasses __() [158] (' ls ') "" ")" listete meine Verzeichnisinhalte auf. Von dort ist nur ein einfacher Schritt zu 'rm -rf \'. Gut gemacht [@Krastanov] (http://Stackoverflow.com/users/669329/krastanov) Du hast bewiesen, dass Sympsy ** nicht ** sicher ist! Sympy ist gefährlich. –