如何在Common Lisp中安全地解析不受信任的输入?鉴于没有parse-float等,read-from-string将执行读取器宏,如#。 (读取时间eval)。
e.g。 (read-from-string"#。(+ 1 2)")=> 3
答案 0 :(得分:7)
我无法找到描述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))
答案 1 :(得分:2)
一般来说,标准代码阅读器非常容易获得并且可以读取多种输入并不意味着您应该使用它来阅读除代码之外的任何内容。
有很多库可以解析很多东西,例如: G。 parse-number
用于Lisp数字格式,fare-csv
用于CSV文件(在许多其他CSV库中),json-streams
用于JSON(再次,许多其他)。对于大多数格式,您只需使用Quicklisp进行system-apropos
查找。