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
}
在我的小游戏项目中,我希望玩家在游戏中操纵一些 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
}