How do you safely parse untrusted input in Common Lisp?

How do you safely parse untrusted input in Common Lisp? Given that there is no parse-float, etc., and that read-from-string will execute read macros such as #. (reading time eval).

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

+4
source share
2 answers

In general, just because a standard code reader is so accessible and can read many types of input does not mean you should use it to read anything other than code.

, . . parse-number Lisp, fare-csv CSV ( CSV-), json-streams JSON (-, ). system-apropos Quicklisp.

+2

, Common Lisp ( - , !), , :

  • io-, , readtable, .. , * read-eval * true, :
  • * read-eval * false ( io-). Sharpign-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))
+7

Source: https://habr.com/ru/post/1624455/


All Articles