Common Lisp 中类似 WAR 文件的东西是什么?

4
我有一个用Lisp编写的系统,可以运行状态机。我想从一个目录中动态加载状态机的定义和任何必需的资源(如图像等),只需给出目录的名称即可。将会有多个不同的状态机。这类似于Apache加载和运行WAR文件,但不完全相同。
我的担忧是,简单地编译和加载文件可能会运行任何东西。理想情况下,我希望仅获取状态机定义,使用资源路径进行配置,并使其可用于执行。现在,我正在尝试加载实现特定基类的类,但这并不直接。是否有标准技术可用于此?
谢谢。

加载和运行WAR文件不是可以运行任何东西吗? - Samuel Edwin Ward
2个回答

3
你是在担心从读取文件中导致任意代码执行的可能性吗?如果是的话,你可以考虑重新定义读取表来排除不需要的符号。
例如,请查看此处,寻找“SAFE-READ-FROM-STRING”的内容。
这不是一个完整的解决方案,但你可以使用#'read获取数据结构,在需要时进行一些安全检查并编译。
如果这不是你所寻找的,请谅解,能否进一步解释你要找的内容?

我认为你的链接并没有指向你想要的地方。 - Samuel Edwin Ward
感谢提供 safe-read-from-string 的指针。这可能是解决方案的一部分。我想我需要实现自己的动态加载方法,查找子类型为已知类并公开用户特定状态机定义的类。 - Patrick

1

如果您想阅读状态机的定义而不执行任意代码,可以考虑使用以下宏:

(defmacro def-state-machine (name (&rest assets) &rest states)
  `(defparameter ,name
     (list
       :assets ',(remove-if-not #'legal-asset? assets)
       :states ',(remove-if-not #'legal-state? states))))

这将创建一个有效资产和状态的列表(因为我不知道你的机器长什么样子,所以我在这里放置一些抽象谓词-它们可以检查语法是否合法,或者参数是否属于某种类型,或者如果资产或状态非法则会抛出错误)。

假设您还需要定义一些函数来运行机器:

(defmacro def-transition (name args &body body)
  `(defun ,name (,@args)
     ,@body))

使用单独的宏定义函数可以进行额外的安全检查。最后,您可以定义阅读器函数:

(defun load-toy-state-machine (directory)
  (let ((path (cl-fad:merge-pathnames-as-file directory #P"machine.lisp"))
        ;(*readtable* (copy-readtable nil))
       )
    ; (make-dispatch-macro-character #\#)
    (with-open-file (stream path :direction :input)
      (do ((form (read stream nil 'done)
                 (read stream nil 'done)))
          ((eql form 'done) T)
        (if (member (car form) '(def-state-machine def-transition))
            (eval form)
            (error "malformed state machine definition file"))))))

此功能仅对允许的宏(def-state-machine和def-transition)进行评估,这些宏具有固定的语法,并可能包含额外的健全性检查。这两个宏均不会执行代码。


不,它不会。如果您想禁用读取宏,您需要修改读取表。我已经在load-toy-state-machine中添加了注释,取消注释会在遇到任何#\#时引发错误。 - Daniel Kochmański
非常棒的想法,谢谢!由于似乎没有已经存在的解决方案,我可能会将这些想法融入到我的解决方案中。感谢您的时间。 - Patrick
我很高兴能够帮助 :-) - Daniel Kochmański

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接