在我的应用程序中,我向用户提供了一些界面,他们可以提供代码和应用程序评估沙箱中的代码(因此eval
不允许)。如果用户覆盖,我需要抓住的东西一些内置函数,例如=
任何想法如何抓住并阻止那件事?(想法是他们不应该这样做)
代码:
(defn =
[]
//some code)
WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/=
一个解决方案可能是:
我试图将警告消息设为String
,但with-out-str
功能无效。
(with-out-str
(defn = []))
;=> ""
还写道with-err-str
(改为 with-out-str 一点点)也不起作用。
(defmacro with-err-str
[& body]
`(let [s# (new java.io.StringWriter)]
(binding [*err* s#]
~@body
(str s#))))
(with-err-str
(defn = []))
;=> ""
需要:"WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/="
答案 0 :(得分:2)
使用eval
:
user=> (with-err-str (eval '(defn - [] 11)))
"WARNING: - already refers to: #'clojure.core/- in namespace: user, being replaced by: #'user/-\n"
user=> (re-seq #"WARNING" (with-err-str (eval '(defn / [] 11))))
("WARNING")
或者您可以在用户代码中重新定义defn
宏,但没有什么能阻止他们使用其他clojure工具重新定义var:
user=> (defmacro defn-safe
#_=> [nam & decls]
#_=> (if (resolve (symbol "clojure.core" (name nam)))
#_=> (print "Whoops")
#_=> (list* `defn (with-meta nam (assoc (meta nam) :private true)) decls)))
#'user/defn-safe
user=> (defn-safe foo [x] (+ x 2))
#'user/foo
user=> (foo 22)
24
user=> (defn-safe = [a b] (- a b))
Whoopsnil
user=>
另一个选择,也许你最好的选择是使用 https://github.com/clojure/tools.analyzer
答案 1 :(得分:2)
clojail处理此问题(以及许多其他事情)。如果你正在寻找沙盒Clojure,我建议你去看看。
答案 2 :(得分:2)
一种解决方案可能是这样的:
(def before (set (vals (ns-map *ns*))))
(defn = [])
(def after (set (vals (ns-map *ns*))))
(clojure.set/difference before after)
;=> #{#'clojure.core/=}