Skip to content
A variant of READ secure against internbombing, excessive input and macro characters.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore
LICENSE
README.md
package.lisp
safe-read.asd
safe-read.lisp
test.lisp

README.md

SAFE-READ

The goal of this project is to create a wrapper around standard Lisp reader to make it able to read input from untrusted sources, such as internet sockets.

Example usage - creating a client-server communication protocol that is based on S-expressions. Using bare READ on both server and client allows the malicious client/server to execute any code on any other networked clients/servers.

As of now, this repository includes variant of READ secure against internbombing, excessive input and macro characters.

Rough definitions

  • Internbombing - the behaviour of READ function, which automatically interns every unknown symbol it doesn't know. This can lead to namespace pollution and blowing the heap with input like (symbol1 symbol2 ... symbol9999999999).
  • Excessive input - causing an out of memory error simply by feeding the READ function an invalid S-expression that does not terminate.
  • Macro characters - functioning of character macros within Lisp syntax, both standard and implementation-defined. They create simple dangers such as #.(let (memleak) (loop (setf memleak (cons memleak memleak)))) along with more subtle ones that are not listed here.

Function SAFE-READ

&optional (stream *standard-input*) s-expression error-status

  • S-EXPRESSION - the read S-expression or NIL if reading was impossible.
  • ERROR-STATUS - one of :INCOMPLETE-INPUT :MALFORMED-INPUT :INPUT-SIZE-EXCEEDED or NIL in case of success.

Variable MAX-INPUT-SIZE

  • Input will not be read beyond this size; SAFE-READ will return :INPUT-SIZE-EXCEEDED as its second value.
  • Defaults to 128 kB.

Details

  • Only lists are accepted as input. Atoms produce :MALFORMED-INPUT.
  • All macro characters other than #\( #\) #\" produce :MALFORMED-INPUT.
  • Package-qualified names (including keywords) produce :MALFORMED-INPUT.
  • All symbols read are non-interned.
  • Read always stops on EOF and newlines.
  • Reading from each stream is buffered, meaning that subsequent calls to SAFE-READ can produce a valid S-expression if it spans over multiple lines. An example is a list containing a string containing a newline.
  • No new S-expression must begin on the line where the previous one ended as they will be ignored.

TODO

  • make it possible to signal conditions instead of relying on the second return value.
  • make it possible to read multiple expressions without newlines
You can’t perform that action at this time.