如何在Common Lisp中安全地解析不受信任的输入?

Sam*_*Sam 5 lisp security common-lisp

如何在Common Lisp中安全地解析不受信任的输入?鉴于没有parse-float等,read-from-string将执行读取器宏,如#.(读取时间eval).

例如(read-from-string"#.(+ 1 2)")=> 3

Jos*_*lor 8

我找不到描述Common Lisp的一些安全输入处理程序的其他问题或评论(如果其他人找到它们,请发表评论!),但至少有两件重要的事情你可以做:

  • 使用标准的io语法确保您正在使用标准的readtable等进行阅读.请注意,这会将*read-eval*绑定为true,因此请务必:
  • *read-eval*绑定为false( with-standard-io-syntax中).这会禁用问题中提到的sharpsign-dot(#.)宏.
(let ((*readtable* (copy-readtable)))
  (set-macro-character #\n (constantly 'injected))
  (read-from-string "(#.(+ 2 5) n)"))
;;=> (7 INJECTED)

(let ((*readtable* (copy-readtable)))
  (set-macro-character #\n (constantly 'injected))
  (with-standard-io-syntax
    (let ((*read-eval* nil))
      (read-from-string "(#.(+ 2 5) n)"))))
;; Evaluation aborted on #<SB-INT:SIMPLE-READER-ERROR
;; "can't read #. while *READ-EVAL* is NIL" {1004DA3603}>.

(let ((*readtable* (copy-readtable)))
  (set-macro-character #\n (constantly 'injected))
  (list (read-from-string "(n)")
        (with-standard-io-syntax
          (let ((*read-eval* nil))
            (read-from-string "(n)")))))
;; ((INJECTED) (N))
Run Code Online (Sandbox Code Playgroud)

  • 确保在`with-standard-io-syntax`中将`*read-eval*`重新绑定到`NIL`,因为后者会将它绑定到默认值`T`! (2认同)

Sva*_*nte 2

一般来说,标准代码阅读器非常容易使用并且可以读取多种输入,但这并不意味着您应该使用它来读取代码以外的任何内容。

有许多库可以解析很多东西,例如parse-numberLisp 数字格式、fare-csvCSV 文件(以及许多其他 CSV 库)、json-streamsJSON(同样还有许多其他库)。对于大多数格式,您只需system-apropos使用 Quicklisp 进行查找即可。