8
(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 アンチウイルスを想像してみてください。

4

3 に答える 3

4

まず第一に、信頼されていないデータ ソースから直接 clojure コードを読み取ってはいけません。代わりに、EDN または別のシリアル化形式を使用する必要があります。

そうは言っても、Clojure 1.5以降、文字列を評価せずに安全に読み取る方法があります。read-string を使用する前に、 read-eval 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 文法の 1 つを拡張して、追加の Clojure フォームを含めることができます。簡単なグーグルでClojure構文のANTLR文法が明らかになりました。必要に応じて欠落している構造をサポートするように変更できます。

ソース コード自体に関する情報を保持する必要がある Clojure ツール用に作成されたライブラリであるSjacketもあります。あなたがやろうとしていることにはぴったりのようですが、個人的には経験がありません。テストから判断すると、パーサーでリーダー マクロがサポートされています。

于 2014-07-04T14:01:11.443 に答える
2

現在のドキュメントによると、信頼されていないデータ ソースを使用したり、読み取ったりすることは絶対にしないでください。readread-string

WARNING: You SHOULD NOT use clojure.core/read or
clojure.core/read-string to read data from untrusted sources.  They
were designed only for reading Clojure code and data from trusted
sources (e.g. files that you know you wrote yourself, and no one
else has permission to modify them).

その目的を念頭に置いて設計されたread-ednorを使用する必要があります。clojure.edn/read

read とread-evalの使用と、それらに関するベスト プラクティスについて、メーリング リストで長い議論がありました。

于 2013-04-21T20:43:51.187 に答える