2017-08-30 12 views
3

在我的应用程序中,我为用户提供了一些界面,他们可以提供代码和应用程​​序评估沙箱内的代码(因此不允许使用eval)。事情是我需要捕捉如果用户覆盖一些内置函数,如?=如何在Clojure中引用“= already”:#'clojure.core/=在namespace:user中被替换为#'user/=“?

任何想法如何捕捉并防止东西(的想法是他们不应该是能够做到这一点)

代码:

(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(改变带出-STR点点)没有正常工作。

(defmacro with-err-str 
    [& body] 
    `(let [s# (new java.io.StringWriter)] 
    (binding [*err* s#] 
     [email protected] 
     (str s#)))) 

(with-err-str 
(defn = [])) 
;=> "" 

极品:"WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/="

回答

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工具重新定义变种:

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

+0

好一个!但我需要没有eval tho :) –

+0

>他们可以提供代码和应用程​​序评估代码 那么你怎么做呢? (编辑问题PLZ) – skrat

+0

是啊,你是对的,但有一些内部的东西,我没有说我需要说我猜,因为它在沙箱中运行eval fn是不允许的:/但我真的很喜欢你的答案会尝试使它适用于我的使用案例 –

1

clojail处理这个(以及许多其他的事情)。如果你正在寻找沙盘Clojure,我建议看一看。

+0

我已经使用clojail,yep也工作! (让作家(java.io.StringWriter。)] (sb'(println“blah”){#'* err * writer})(str writer));返回“blah \ n” –

2

一种解决方案可能是这样的:

(def before (set (vals (ns-map *ns*)))) 

(defn = []) 

(def after (set (vals (ns-map *ns*)))) 

(clojure.set/difference before after) 

;=> #{#'clojure.core/=} 
相关问题