{"id":16411066,"url":"https://github.com/phoe/safe-read","last_synced_at":"2026-03-02T17:01:59.231Z","repository":{"id":45116003,"uuid":"64552363","full_name":"phoe/safe-read","owner":"phoe","description":"A variant of READ secure against internbombing, excessive input and macro characters.","archived":false,"fork":false,"pushed_at":"2022-10-10T21:19:14.000Z","size":32,"stargazers_count":44,"open_issues_count":3,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-06T03:23:32.523Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phoe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-07-30T16:05:23.000Z","updated_at":"2024-11-16T10:46:08.000Z","dependencies_parsed_at":"2023-01-19T20:16:38.222Z","dependency_job_id":null,"html_url":"https://github.com/phoe/safe-read","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoe%2Fsafe-read","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoe%2Fsafe-read/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoe%2Fsafe-read/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoe%2Fsafe-read/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phoe","download_url":"https://codeload.github.com/phoe/safe-read/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240415660,"owners_count":19797671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T06:44:28.530Z","updated_at":"2026-03-02T17:01:54.187Z","avatar_url":"https://github.com/phoe.png","language":"Common Lisp","readme":"# SAFE-READ\nThe 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.\n\nExample 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.\n\nAs of now, this repository includes variant of READ secure against internbombing, excessive input and macro characters.\n\n### Rough definitions\n* **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)`.\n* **Excessive input** - causing an out of memory error simply by feeding the READ function a large enough S-expression.\n* **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.\n\n### Function SAFE-READ\n_`\u0026optional (stream *standard-input*) use-list` **→** `s-expression error-status`_\n  * `STREAM` - a stream to read from.\n  * `USE-LIST` - a list of package designators. Reading will occur in a temporary package that uses these packages.\n  * `S-EXPRESSION` - the read S-expression or NIL if reading was impossible.\n  * `ERROR-STATUS` - one of `:INCOMPLETE-INPUT :MALFORMED-INPUT :INPUT-SIZE-EXCEEDED` or NIL in case of success.\n\n### Variable *MAX-INPUT-SIZE*\n  * Input will not be read beyond this size; SAFE-READ will return `:INPUT-SIZE-EXCEEDED` as its second value.\n  * Defaults to 128 kB.\n\n### Details\n  * Only lists are accepted as input. Atoms produce `:MALFORMED-INPUT`.\n  * All macro characters other than `#\\(` and `#\\\"` produce `:MALFORMED-INPUT`. (`#\\)` is only accepted at the end of a list.)\n  * Package-qualified names (including keywords) produce `:MALFORMED-INPUT`.\n  * All symbols read are non-interned, with the exceptions of symbols exported from the packages listed in `USE-LIST` which are interned in these respective packages.\n  * Reading always stops on EOF and newlines.\n  * 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.\n  * Limitation: no new S-expression must begin on the line where the previous one ended as they will be ignored.\n\n### TODO\n  * `make it possible to signal conditions instead of relying on the second return value.`\n  * `make it possible to read multiple expressions without newlines`\n","funding_links":[],"categories":["Recently Updated","Online editors ##"],"sub_categories":["[Apr 28, 2025](/content/2025/04/28/README.md)","Third-party APIs"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphoe%2Fsafe-read","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphoe%2Fsafe-read","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphoe%2Fsafe-read/lists"}