Common lisp 公共Lisp中格式指令的安全解析

Common lisp 公共Lisp中格式指令的安全解析,common-lisp,string-formatting,sanitization,Common Lisp,String Formatting,Sanitization,我想从输入文件(用户可能修改过,也可能没有修改过)中读取字符串。我想把这个字符串当作一个格式指令,用固定数量的参数调用。但是,我知道一些格式指令(特别是我想到的~/)可能会被用于注入函数调用,这使得这种方法本质上是不安全的 在公共Lisp中使用read解析数据时,该语言提供*read eval*动态变量,该变量可以设置为nil以禁用#代码注入。我正在寻找类似的东西来防止格式指令中的代码注入和任意函数调用。您需要担心的不仅仅是~/。pretty printer功能有很多代码扩展的可能性,甚至~A也

我想从输入文件(用户可能修改过,也可能没有修改过)中读取字符串。我想把这个字符串当作一个格式指令,用固定数量的参数调用。但是,我知道一些格式指令(特别是我想到的
~/
)可能会被用于注入函数调用,这使得这种方法本质上是不安全的


在公共Lisp中使用
read
解析数据时,该语言提供
*read eval*
动态变量,该变量可以设置为
nil
以禁用
#
代码注入。我正在寻找类似的东西来防止格式指令中的代码注入和任意函数调用。

您需要担心的不仅仅是~/。pretty printer功能有很多代码扩展的可能性,甚至~A也会导致问题,因为对象可能定义了打印对象的方法。例如:

(defclass x () ())

(defmethod print-object ((x x) stream)
  (format *error-output* "Executing arbitrary code...~%")
  (call-next-method x stream))

CL-USER>(格式t“~A”(生成实例'x))
正在执行任意代码。。。
#
无

我认为您需要为自己定义哪些指令是安全的,使用您认为重要的任何标准,然后只包括那些。

< P>如果用户不能引入自定义代码,但仅设置字符串,则可以避免“代码>打印对象< /代码>的问题。请记住使用(或其自定义版本)来控制您将生成的确切输出类型(想想
*print base*
,…)

您可以扫描输入字符串以检测是否存在
~/
(但
~/
有效)并拒绝解释包含黑名单结构的格式。 但是,某些分析比较困难,您可能需要在运行时执行操作

例如,如果格式字符串格式不正确,您可能会遇到一个必须处理的错误(此外,您可能会为预期参数指定错误值)

即使用户不是恶意的,您也可能在迭代构造方面存在问题:

~{<X>~:*~}
~{:*~}
。。。从不停止,因为
~:*
倒带当前参数。为了处理这个问题,你必须考虑<代码> <代码>,或者不打印一些东西。您可以实施这两种策略:

  • 设置超时以限制格式化所需的时间
  • 当写入太多(例如写入字符串缓冲区)时,使底层流到达文件末尾

可能还有其他我目前看不到的问题,请小心。

谢谢。我甚至没有想过无限循环的问题。有了这些问题,我可能会为格式说明符编写自己的微语言,而不是尝试调整
格式
@SilvioMayolo这也是一个好方法。但花点时间看看是否存在其他形式:我正在考虑国际刑警组织,但可能还有其他形式。祝你好运@约书亚·泰勒:我了解到了这一点:-)
~{<X>~:*~}