Zunächst sollten Sie nie clojure code direkt von nicht vertrauenswürdigen Datenquellen lesen. Sie sollten stattdessen EDN oder ein anderes Serialisierungsformat verwenden.
Seit Clojure 1.5 gibt es eine Art sicherer Weg, Strings zu lesen, ohne sie auszuwerten. Sie sollten die Variable read-eval var vor der Verwendung von read-string an false binden. In Clojure 1.4 und früher führte dies möglicherweise zu Seiteneffekten, die durch den Aufruf von Java-Konstruktoren verursacht wurden. Diese Probleme wurden seither behoben. Hier
ist einige Beispiel-Code:
(defn read-string-safely [s]
(binding [*read-eval* false]
(read-string s)))
(read-string-safely "#=(eval (def x 3))")
=> RuntimeException EvalReader not allowed when *read-eval* is false. clojure.lang.Util.runtimeException (Util.java:219)
(read-string-safely "(def x 3)")
=> (def x 3)
(read-string-safely "#java.io.FileWriter[\"precious-file.txt\"]")
=> RuntimeException Record construction syntax can only be used when *read-eval* == true clojure.lang.Util.runtimeException (Util.java:219)
Bezüglich Leser Makros
Der Versand Makro (#) und getaggt Literale werden bei Lesezeit aufgerufen. In Clojure-Daten gibt es keine Repräsentation für sie, da zu dieser Zeit alle diese Konstrukte verarbeitet wurden. Soweit ich weiß, gibt es keinen eingebauten Weg, um einen Syntaxbaum des Clojure-Codes zu erzeugen.
Sie müssen einen externen Parser verwenden, um diese Informationen beizubehalten. Entweder rollen Sie Ihren eigenen benutzerdefinierten Parser oder Sie können einen Parser-Generator wie Instaparse und ANTLR verwenden. Eine vollständige Clojure-Grammatik für eine dieser Bibliotheken könnte schwer zu finden sein, aber Sie könnten eine der EDN-Grammatiken um die zusätzlichen Clojure-Formulare erweitern. Eine schnelle Google ergab an ANTLR grammar for Clojure syntax, Sie könnten es ändern, um die Konstrukte zu unterstützen, die bei Bedarf fehlen.
Es gibt auch Sjacket eine Bibliothek für Clojure-Tools, die Informationen über den Quellcode selbst behalten müssen. Es scheint wie eine gute Lösung für das, was Sie versuchen, aber ich habe keine Erfahrung damit persönlich. Gemessen an den Tests hat es Unterstützung für Lesemakros in seinem Parser.
könnte ein viel des Guten, aber ein nehmen schau dir [clojail] an (https://github.com/flatland/clojail) –
Benutze read-string mit \ * read-eval \ * auf false setzen – Ankur
Doc sagt das sogar mit [\ * read-eval * false] immer noch nicht entworfen, um sicher zu sein. Und wie analysiert man den Code, der auf # = angewiesen ist und Makros liest? Ich erwarte, dass sie irgendwie in Datenstrukturen erscheinen, ohne tatsächlich ausgeführt zu werden. –