(def evil-code (str "(" (slurp "/mnt/src/git/clj/clojure/src/clj/clojure/core.clj") ")" ))
(def r (read-string evil-code ))
有效,但不安全
(def r (clojure.edn/read-string evil-code))
RuntimeException Map literal must contain an even number of forms clojure.lang.Util.runtimeException (Util.java:219)
不起作用...
如何安全地将 Clojure 代码(保留所有“#”本身)安全地读入树中?想象一下,一个 Clojure 防病毒软件想要扫描代码中是否存在威胁,并且想要使用数据结构,而不是纯文本。
首先,您永远不应该直接从不受信任的数据源读取 clojure 代码。您应该使用 EDN 或其他序列化格式。
话虽这么说,从 Clojure 1.5 开始,有一种安全的方法可以读取字符串而不需要评估它们。你应该绑定读取-评估在使用 read-string 之前将 var 设置为 false。在 Clojure 1.4 及更早版本中,这可能会因调用 java 构造函数而产生副作用。这些问题现已得到解决。
这是一些示例代码:
(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)
关于阅读器宏
调度宏 (#) 和标记文字在读取时调用。 Clojure 数据中没有它们的表示,因为到那时这些结构都已被处理。据我所知,没有构建方法来生成 Clojure 代码的语法树。
您将必须使用外部解析器来保留该信息。您可以使用自己的自定义解析器,也可以使用 Instaparse 和 ANTLR 等解析器生成器。可能很难找到这两个库的完整 Clojure 语法,但您可以扩展其中一个 EDN 语法以包含其他 Clojure 形式。谷歌快速揭晓Clojure 语法的 ANTLR 语法,如果需要,您可以更改它以支持缺少的结构。
还有Sjacket为 Clojure 工具制作的库,需要保留有关源代码本身的信息。这似乎很适合你想做的事情,但我个人没有任何经验。从测试来看,它的解析器确实支持读取器宏。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)