Remove/Whitelist Clojure 中的所有绑定

Remove/Whitelist all bindings in Clojure

在我的小游戏项目中,我希望玩家在游戏中操纵一些 in-game 东西,编写一些 Clojure 脚本。所以,我下载了 Clojure 库并使用了这段代码:

private val eval = Clojure.`var`("clojure.core", "eval")

fun eval(code: String): Any? =
    try {
        eval.invoke(Clojure.read("(do $code)"))
    } catch(e: Exception) {
        e.printStackTrace()
        null
    }

但问题是,通过这样做,玩家可以操纵整个程序,因为它与游戏代码在相同的环境中运行。最简单的例子是(System/exit 0).

我的问题是 - 如何从我的脚本上下文中删除所有 Clojure 绑定,除了一些基本的预定义内容,如数学运算符、collection 魔法等等?

此外,我可以使用 eval.invoke("(def do-magic [x] (println "magic"))") 放置我自己的绑定(用于将这些脚本连接到实际游戏逻辑),但是有没有更一致的方法来做到这一点?

更新: 我需要做 really simple 东西,比如数学和简单的函数。也许有点 collection 魔法。所以我需要阻止 除了这个东西之外的所有东西,所以任何不安全的代码根本不存在。

这种技术被称为 sandbox,简单地谷歌搜索“clojure 沙箱”最终让我找到了关于这个主题的文章。

更新: 我需要 whitelist 东西,而不是 blacklist,因为它在 Internet 上使用。 花了一整天,但终于让这个正常工作

private val eval = Clojure.`var`("clojure.core", "eval")

val whitelist = listOf("+", "-", "*", "/", "=") // example

init {
    val wh = whitelist.joinToString(" ", "[", "]") { "\"$it\"" }
    eval("""
        (let [wh (vec (map symbol $wh))]
          (doseq [n (all-ns) :let [n (ns-name n)]]
            (if (= (str n) "clojure.core")
              (doseq [[k _] (ns-map n) :when (not (some (fn [x] (= x k)) wh))]
                (ns-unmap n k))
              (remove-ns n))))
    """)
}

fun eval(code: String): Any? =
    try {
        eval.invoke(Clojure.read("(do $code)"))
    } catch(e: Exception) {
        e.printStackTrace()
        null
    }