This SRFI is currently in final status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to
email@example.com. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.
This SRFI provides two libraries for use with R7RS that provide a
way to sandbox the
eval procedure to make it safer to use
in evaluating Scheme expressions of doubtful provenance. The intention
is to call
eval, passing it an S-expression representing a
Scheme procedure and the environment defined by one of these libraries.
Since code evaluated by
eval runs in a null lexical
environment, the resulting procedure can then be invoked with less
concern about possible side effects.
Use of these libraries does not provide any sort of safety guarantee. There are still many loopholes uncaught, including attempts to process circular structure and over-allocation of memory. The claim is only that the probability of such an attack is reduced, not that it is eliminated. However, using these libraries is a simple provision that is easy to implement and easy to use. For higher safety, it can readily be combined with other provisions.
eval procedure, though part of the language
since R5RS and commonplace in Scheme implementations long before that,
has always been considered radically unsafe. In the R6RS and R7RS,
this is not entirely true.
With the help of the
code can be evaluated in an immutable global environment
containing only specified libraries. This SRFI provides
two such environments, structured as R6RS or R7RS libraries.
The intention is that the programmer call
(eval s (environment '(srfi 172))),
where s is an S-expression
representing a procedure (typically a list whose
The resulting procedure can be called with increased assurance that it
will not gain access to or modify any Scheme object except those that
are reachable from whatever is passed in as an argument.
(srfi 172 functional)
is passed to
eval in place of
the procedure most likely cannot mutate anything at all.
Note that while some I/O operations are provided by these libraries, the only kinds of ports that can be created are string and bytevector ports.
Warning: If an implementation coalesces two constants (quoted
or self-evaluating) that are the same in the sense of
so that they also become constant in the sense of eq?, then a mutation
of one constant will affect the value of the other unless they are marked
immutable when read in; Scheme allows this but does not require it:
(define (foo x) (set-car! '(a . b) x) (car '(a . b))) ; compile the file with MIT Scheme and load it (foo 5) => 5 ; instead of a because the two (a . b) constants are coalesced
Such changes provide a covert channel between the sandbox and an object outside it that has been made the same object under the covers, and there is nothing this SRFI can do about it. (Example due to Taylor Campbell.)
(srfi 172) includes the following 284 variables
and syntax keywords from R7RS-small. They are believed to be safe in the
sense that they cannot affect or be affected by the outside world except
through the arguments passed to them.
No distinctions are
made between the individual R7RS-small libraries, though implementations
that lack one or more libraries would have to bind the missing names
to calls on
This SRFI does not require that the procedures and syntax definitions it exports are exactly the same as those exported by the various R7RS standard libraries. In particular, wrappers or alternative versions that signal errors on implementation-specified behavior are recommended.
- * / + < <= = => > >= abs acos and angle append apply asin assoc assq assv atan begin boolean? boolean=? bytevector bytevector? bytevector-append bytevector-copy bytevector-copy! bytevector-length bytevector-u8-ref bytevector-u8-set! caaaar caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar caddar cadddr caddr cadr call/cc call-with-current-continuation call-with-port call-with-values car case case-lambda cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr cddr cdr ceiling char? char<? char<=? char=? char>? char>=? char->integer char-alphabetic? char-ci<? char-ci<=? char-ci=? char-ci>? char-ci>=? char-downcase char-foldcase char-lower-case? char-numeric? char-upcase char-upper-case? char-whitespace? close-input-port close-output-port close-port complex? cond cond-expand cons cos delay delay-force denominator digit-value do dynamic-wind else eof-object eof-object? eq? equal? eqv? error error-object? error-object-irritants error-object-message even? exact exact? exact-integer? exact-integer-sqrt exp expt finite? floor floor/ floor-quotient floor-remainder force for-each gcd get-output-bytevector get-output-string guard if imag-part inexact inexact? infinite? input-port? integer? integer->char lambda lcm length let let* let*-values letrec letrec* let-values list list? list->string list->vector list-copy list-ref list-set! list-tail log magnitude make-bytevector make-list make-parameter make-polar make-promise make-rectangular make-string make-vector map max member memq memv min modulo nan? negative? newline not null? number? number->string numerator odd? open-input-bytevector open-input-string open-output-bytevector open-output-string or output-port? pair? peek-char peek-u8 parameterize port? positive? procedure? promise? quasiquote quote quotient raise raise-continuable rational? rationalize read-bytevector read-bytevector! read-char read-error? read-line read-string read-u8 real? real-part remainder reverse round set! set-car! set-cdr! sin sqrt square string string? string<? string<=? string=? string>? string>=? string->list string->number string->utf8 string->vector string-append string-ci<? string-ci<=? string-ci=? string-ci>? string-ci>=? string-copy string-copy! string-downcase string-fill! string-foldcase string-for-each string-length string-map string-ref string-set! string-upcase substring symbol? symbol=? symbol->string tan textual-port? truncate truncate/ truncate-quotient truncate-remainder unless unquote unquote-splicing utf8->string values vector vector? vector->list vector->string vector-append vector-copy vector-copy! vector-fill! vector-for-each vector-length vector-map vector-ref vector-set! when with-exception-handler write-bytevector write-char write-string write-u8 zero?
(srfi 172 functional) exports all of
the exports of
It therefore exports 251 identifiers.
A conforming implementation could be created entirely from this description.
Implementations of the two libraries for Chibi can be found in the repository of this SRFI and in srfi-172.tgz.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.