1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Add allow-legacy-syntax-objects? parameter

* module/ice-9/psyntax.scm (syntax?): Only recognize legacy syntax
  objects if the new allow-legacy-syntax-objects? parameter is true.
* module/ice-9/boot-9.scm (allow-legacy-syntax-objects?): New
  parameter.
* doc/ref/api-macros.texi (Syntax Transformer Helpers): Document the
  horrible situation with legacy syntax objects.
* NEWS: Add entry.
This commit is contained in:
Andy Wingo 2017-03-28 21:27:11 +02:00
parent a42bfae65f
commit ce934bcd43
4 changed files with 68 additions and 2 deletions

20
NEWS
View file

@ -5,6 +5,26 @@ See the end for copying conditions.
Please send Guile bug reports to bug-guile@gnu.org.
Changes in 2.2.1 (since 2.2.0):
* Notable changes
** Syntax objects are now a distinct type
It used to be that syntax objects were represented as a tagged vector.
These values could be forged by users to break scoping abstractions,
preventing the implementation of sandboxing facilities in Guile. We are
as embarrassed about the previous situation as we pleased are about the
fact that we've fixed it.
Unfortunately, during the 2.2 stable series (or at least during part of
it), we need to support files compiled with Guile 2.2.0. These files
may contain macros that contain legacy syntax object constants. See the
discussion of "allow-legacy-syntax-objects?" in "Syntax Transformer
Helpers" in the manual for full details.
Changes in 2.2.0 (changes since the 2.0.x stable release series):

View file

@ -791,6 +791,44 @@ Return the source properties that correspond to the syntax object
@var{x}. @xref{Source Properties}, for more information.
@end deffn
And now, a bit of confession time. Guile's syntax expander originates
in code from Chez Scheme: a version of the expander in Chez Scheme that
was made portable to other Scheme systems. Way back in the mid-1990s,
some Scheme systems didn't even have the ability to define new abstract
data types. For this reason, the portable expander from Chez Scheme
that Guile inherited used tagged vectors as syntax objects: vectors
whose first element was the symbol, @code{syntax-object}.
At the time of this writing it is 2017 and Guile still has support for
this strategy. It worked for this long because no one ever puts a
literal vector in the operator position:
@example
(#(syntax-object ...) 1 2 3)
@end example
But this state of affairs was an error. Because syntax objects are just
vectors, this makes it possible for any Scheme code to forge a syntax
object which might cause it to violate abstraction boundaries. You
can't build a sandboxing facility that limits the set of bindings in
scope when one can always escape that limit just by evaluating a special
vector. To fix this problem, Guile 2.2.1 finally migrated to represent
syntax objects as a distinct type with a distinct constructor that is
unavailable to user code.
However, Guile still has to support ``legacy'' syntax objects, because
it could be that a file compiled with Guile 2.2.0 embeds syntax objects
of the vector kind. Whether the expander treats the special tagged
vectors as syntax objects is now controllable by the
@code{allow-legacy-syntax-objects?} parameter:
@deffn {Scheme Procedure} allow-legacy-syntax-objects?
A parameter that indicates whether the expander should support legacy
syntax objects, as described above. For ABI stability reasons, the
default is @code{#t}. Use @code{parameterize} to bind it to @code{#f}.
@xref{Parameters}.
@end deffn
Guile also offers some more experimental interfaces in a separate
module. As was the case with the Large Hadron Collider, it is unclear
to our senior macrologists whether adding these interfaces will result

View file

@ -299,6 +299,9 @@ This is handy for tracing function calls, e.g.:
(define (absolute-file-name? file-name) #t)
(define (open-input-file str) (open-file str "r"))
;; Temporary definition; replaced by a parameter later.
(define (allow-legacy-syntax-objects?) #f)
;;; {and-map and or-map}
;;;
;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
@ -1423,11 +1426,15 @@ CONV is not applied to the initial value."
;;; Once parameters have booted, define the default prompt tag as being
;;; a parameter.
;;; a parameter, and make allow-legacy-syntax-objects? a parameter.
;;;
(set! default-prompt-tag (make-parameter (default-prompt-tag)))
;; Because code compiled with Guile 2.2.0 embeds legacy syntax objects
;; into its compiled macros, we have to default to true, sadly.
(set! allow-legacy-syntax-objects? (make-parameter #t))
;;; {Languages}

View file

@ -473,7 +473,8 @@
(define (syntax-object? x)
(or (syntax? x)
(and (vector? x)
(and (allow-legacy-syntax-objects?)
(vector? x)
(= (vector-length x) 4)
(eqv? (vector-ref x 0) 'syntax-object))))
(define (make-syntax-object expression wrap module)