【问题标题】:Remove/Whitelist all bindings in Clojure删除 Clojure 中的所有绑定/将其列入白名单
【发布时间】:2016-04-10 16:32:02
【问题描述】:

在我的小游戏项目中,我希望玩家直接在游戏中编写一些 Clojure 脚本来操作游戏中的一些内容。所以,我下载了 Clojure lib 并使用了这段代码:

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 绑定,除了一些基本的预定义内容,如数学运算符、集合魔法等?

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

更新: 我需要做真的 简单 的东西,比如数学和跳来跳去简单的函数。也许有点收集魔法。所以我需要阻止一切除了这些东西,所以任何不安全的代码根本不存在。

【问题讨论】:

  • 使用 cljs 代替 clj 并通过嵌入式 js eval(例如 rhino)运行播放器代码怎么样?这对于沙盒来说可能会简单得多
  • 哦,用谷歌搜索这类东西是正确的! sandbox!非常感谢,找到了很多关于它的文章,终于

标签: binding clojure eval


【解决方案1】:

这种技术被称为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
    }

【讨论】:

    猜你喜欢
    • 2017-10-27
    • 2021-03-26
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 2012-10-06
    • 1970-01-01
    相关资源
    最近更新 更多