我需要隐藏危险的功能,例如, cl:开放从互联网下载的第三方代码。
所以我可以这样做:
(package :dangerous (:use :cl))
(import 'cl:open :dangerous)
(import 'cl:export :dangerous)
...
(unexport 'open :cl)
(unexport 'export :cl)
...
; instead of cl:export which hided implement own export fn and then import it to untrusted package
(load "untrusted-lib.lisp")
据我了解,不受信任的代码根本无法调用 cl:open,除非使用 cl::open,对吗? 可以通过其他方式调用 cl:open 吗?
乍一看,如果禁用双冒号访问,CL 有可能限制对 API 的访问。 理论上可以创建安全管理器(权限访问管理器) 是否可以禁用 SBCL 和其他 CL 编译器的“::”调用?
您给出的代码非常不符合要求(您修改了 CL 包),并且即使符合要求也无法解决问题。
这是击败它的简单方法:
(setf (fdefinition 'my-open)
(do-symbols (s :cl)
(when (string= (symbol-name s) "OPEN")
(return (fdefinition s)))))
这是另一个(这个更好,但我后来想到的):
(setf (fdefinition 'my-open)
(fdefinition (find-symbol "OPEN" :cl)))
还会有更多。
因此,这样的方法确实是解决问题的无望方法,即使 Common Lisp 是合法的,但事实并非如此。
CL 并不是一种在设计时就考虑到这种限制的语言,因此好的解决方案是介于困难和不可能之间的。
也许一种方法如下。
您可能还希望有一个“清理”阶段:在每次评估之前隐藏系统的包状态(这很费力但可能),然后在评估之后检查您没有预料到的任何变化。 您可能还需要某种可以围绕评估的超时机制。
我并不声称这就足够了。 我并不认为这在 CL 中是完全“可能”的。 但类似这样的东西可能会有所帮助,如果是的话。 我碰巧知道 conduit packages
最初是作为系统的一部分编写的,该系统试图做到这一点。 因此,这是定义一个仅重新导出部分内容的包的好方法,例如CL
:
(define-conduit-package :just-conses
(:extends/including :cl
#:cons #:car #:cdr #:nil ...))