Sam*_*Sam 5 lisp security common-lisp
如何在Common Lisp中安全地解析不受信任的输入?鉴于没有parse-float等,read-from-string将执行读取器宏,如#.(读取时间eval).
例如(read-from-string"#.(+ 1 2)")=> 3
我找不到描述Common Lisp的一些安全输入处理程序的其他问题或评论(如果其他人找到它们,请发表评论!),但至少有两件重要的事情你可以做:
(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)
一般来说,标准代码阅读器非常容易使用并且可以读取多种输入,但这并不意味着您应该使用它来读取代码以外的任何内容。
有许多库可以解析很多东西,例如parse-number
Lisp 数字格式、fare-csv
CSV 文件(以及许多其他 CSV 库)、json-streams
JSON(同样还有许多其他库)。对于大多数格式,您只需system-apropos
使用 Quicklisp 进行查找即可。