12.8 Syntax Taints

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

▼ | 12 | Macros

12.1 | Pattern-Based Syntax Matching
12.2 | Syntax Object Content
12.3 | Syntax Object Bindings
12.4 | Syntax Transformers
12.5 | Syntax Parameters
12.6 | Local Binding with Splicing Body
12.7 | Syntax Object Properties
12.8 | Syntax Taints
12.9 | Expanding Top-Level Forms
12.10 | File Inclusion
12.11 | Syntax Utilities

On this page:

syntax-tainted?
syntax-arm
syntax-protect
syntax-disarm
syntax-rearm
syntax-taint

top ← prev up next →

#### 12.8`` Syntax Taints

> > > Syntax Taints in The Racket Guide introduces syntax taints.

The tamper status of a syntax object is either tainted, armed, or clean:

- A tainted identifier is rejected by the macro expander for use as either a binding or expression. If a syntax object is tainted, then any syntax object in the result of (syntax-e stx) is tainted, and datum->syntax with stx as its first argument produces a tainted syntax object.

  Other derived operations, such as pattern matching in syntax-case, also taint syntax objects when extracting them from a tainted syntax object.

- An armed syntax object has a set of dye packs, which creates taints if the armed syntax object is used without first disarming the dye packs. In particular, if a syntax object is armed, syntax-e, datum->syntax, quote-syntax, and derived operations effectively treat the syntax object as tainted. The macro expander, in contrast, disarms dye packs before pulling apart syntax objects.

  Each dye pack, which is added to a syntax object with the syntax-arm function, is keyed by an inspector. A dye pack can be disarmed using syntax-disarm with an inspector that is the same as or a superior of the dye pack’s inspector.

- A clean syntax object has no immediate taints or dye packs, although it may contain syntax objects that are tainted or armed.

Taints cannot be removed, and attempting to arm a syntax object that is already tainted has no effect on the resulting syntax object.

The macro expander disarms any syntax object that it encounters in an expression position or as a module body. A syntax object is therefore disarmed when it is provided to a syntax transformer. The transformer’s result, however, is rearmed by copying to it any dye packs that were originally attached to the transformer’s input. The rearming process obeys the following rules:

- If the result has a 'taint-mode property (see Syntax Object Properties) that is 'opaque, then dye packs are attached to the immediate syntax object.

- If the result has a 'taint-mode property that is 'none, then no dye pack is attached to the syntax object. The 'none mode is rarely appropriate.

- If the result has a 'taint-mode property that is 'transparent, then the dye packs are propagated recursively to syntax object that corresponds to elements of the syntax object’s datum as a list (or, more precisely, to the cars of the datum as reached by any number of cdrs), and the immediate syntax object loses its lexical context; If the immediate syntax object is already armed, then recursive propagation taints the elements. Recursive propagation uses syntax properties and shapes, as for the immediate rearming.

- If the result has a 'taint-mode property that is 'transparent-binding, then dye packs are attached in a way similar to 'transparent, but further treating the syntax object corresponding to the second list element as having a 'transparent value for the 'taint-mode property if it does not already have a 'taint-mode property value.

- If the result has no 'taint-mode property value, but its datum is a pair, and if the syntax object corresponding to the car of the pair is an identifier bound to begin, module, or #%plain-module-begin, then dye packs are propagated as if the syntax object had the 'transparent property value.

- If the result has no 'taint-mode property value, but its datum is a pair, and if the syntax object corresponding to the car of the pair is an identifier bound to define-values or define-syntaxes, then dye packs are propagated as if the syntax object had the 'transparent-binding property value.

For backward compatibility, a 'certify-mode property is treated the same as a 'taint-mode property if the former is not attached. To avoid accidental transfer of a 'taint-mode or 'certify-mode property value, the expander always removes any 'taint-mode and 'certify-mode property on a syntax object that is passed to a syntax transformer.

> procedure (syntax-tainted? stx) → boolean?
> stx : syntax?

Returns #t if stx is tainted, #f otherwise.

> procedure (syntax-arm stx [inspector use-mode?]) → syntax?
> stx : syntax?
> inspector : (or/c inspector? #f) = #f
> use-mode? : any/c = #f

Produces a syntax object like stx, but armed with a dye pack that is keyed by inspector.

A #f value for inspector is equivalent to an inspector that depends on the current dynamic context:

- when applying a syntax transformer is being applied, the declaration-time code inspector of the module in which a syntax transformer was bound;

- when a module is being visited, the module’s declaration-time code inspector;

- (current-code-inspector), otherwise.

If use-mode? is #f, then if stx is tainted or already armed with the key inspector, the result is stx.

If use-mode? is a true value, then a dye pack is not necessarily added directly to stx. Instead, the dye pack is pushed to interior syntax objects in the same way that the expander pushes armings into a syntax transformer’s results when rearming (based on a 'taint-mode syntax property or identifier bindings); see the expander’s rearming rules for more information. To the degree that pushing dye packs into a syntax object must destructure stx, existing taints or dye packs can lead to tainted results rather than armed results.

> procedure (syntax-protect stx) → syntax?
> stx : syntax?

Equivalent to (syntax-arm stx #f #t).

> procedure (syntax-disarm stx inspector) → syntax?
> stx : syntax?
> inspector : (or/c inspector? #f)

Produces a disarmed version of stx, removing any immediate dye packs that match inspector. An inspector matches when it is either the same as or a super-inspector of the dye pack’s inspector. A #f value for inspector is replaced by a specific inspector in the same way as for syntax-arm.

> procedure (syntax-rearm stx from-stx [use-mode?]) → syntax?
> stx : syntax?
> from-stx : syntax?
> use-mode? : any/c = #f

Produces a rearmed or tainted version of stx by adding all immediate taints and dye packs of from-stx.

If use-mode? is a true value, stx is not necessarily tainted or armed directly. Instead, taints or dye packs are pushed to interior syntax objects in the same way as for syntax-arm or rearming by the expander.

> procedure (syntax-taint stx) → syntax?
> stx : syntax?

Returns tainted version of stx—equivalent to (datum->syntax (syntax-arm stx) (syntax-e stx) stx stx)—or stx if it is already tainted.
top ← prev up next →