Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you securely parse untrusted input in Common Lisp?

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

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

like image 502
Sam Avatar asked Jan 15 '16 14:01

Sam


2 Answers

I can't find the other question or comment that described some of the safe input handling procedures for Common Lisp (if someone else finds them, please post a comment!), but there are at least two important things that you might do:

  • Use with-standard-io-syntax to make sure that you're reading with the standard readtable, etc. Note that this will bind *read-eval* to true, so be sure to also:
  • Bind *read-eval* to false (within with-standard-io-syntax). This disables the sharpsign-dot (#.) macro mentioned in the question.
(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))
like image 110
Joshua Taylor Avatar answered Nov 16 '22 22:11

Joshua Taylor


Generally, just that the standard code reader is so readily available and can read many kinds of input does not mean that you should use it to read anything but code.

There are many libraries for parsing a lot of things, e. g. parse-number for the Lisp number formats, fare-csv for CSV files (among many other CSV libraries), json-streams for JSON (again, many others). For most formats, you can just do a system-apropos lookup with Quicklisp.

like image 43
Svante Avatar answered Nov 16 '22 21:11

Svante