► |  | The Racket Guide

1 | Welcome to Racket
2 | Racket Essentials
3 | Built-In Datatypes
4 | Expressions and Definitions
5 | Programmer-Defined Datatypes
6 | Modules
7 | Contracts
8 | Input and Output
9 | Regular Expressions
10 | Exceptions and Control
11 | Iterations and Comprehensions
12 | Pattern Matching
13 | Classes and Objects
14 | Units
15 | Reflection and Dynamic Evaluation
16 | Macros
17 | Creating Languages
18 | Concurrency and Synchronization
19 | Performance
20 | Parallelism
21 | Running and Creating Executables
22 | More Libraries
23 | Dialects of Racket and Scheme
24 | Command-Line Tools and Your Editor of Choice
| Bibliography
| Index

▼ | 15 | Reflection and Dynamic Evaluation

15.1 | eval
15.2 | Manipulating Namespaces
15.3 | Scripting Evaluation and Using load
15.4 | Code Inspectors for Trusted and Untrusted Code

top ← prev up next →

#### 15.4`` Code Inspectors for Trusted and Untrusted Code

Code inspectors provide the mechanism for determining which modules are trusted to use functions like module->namespace or unsafe modules like ffi/unsafe. When a module is declared, the value of current-code-inspector is associated to the module declaration. When a module is instantiated (i.e., when the body of the declaration is actually executed), a sub-inspector is created to guard the module’s exports. Access to the module’s protected exports requires a code inspector that is stronger (i.e., higher in the inspector hierarchy) than the module’s instantiation inspector; note that a module’s declaration inspector is always stronger than its instantiation inspector, so modules are declared with the same code inspector can access each other’s exports.

To distinguish between trusted an untrusted code, load trusted code first, then set current-code-inspector to the result of (make-inspector (current-code-inspector)) to install a weaker inspector, and finally load untrusted code with the weaker inspector in place. The weaker inspector should stay in place when any untrusted code is run. If necessary, trusted code can restore the original inspector temporarily during the dynamic extent of trusted code (as long as it does not call back into untrusted code).

Syntax-object constants within a module, such as literal identifiers in a template, retain the inspector of their source module. In this way, a macro from a trusted module can be used within an untrusted module, and protected identifiers in the macro expansion still work, even through they ultimately appear in an untrusted module. Typically, such identifiers should be armed, so that they cannot be extracted from the macro expansion and abused by untrusted code.

When datum->syntax is used to transfer the context of a syntax object to another, then it may taint the resulting syntax object. Even if the source syntax object is not armed, however, the resulting syntax object may have limited access to bindings; datum->syntax will not transfer an inspector from the source syntax object unless datum->syntax is called during the expansion of a macro whose module’s declaration-time code inspector is strong enough. More generally, datum->syntax chooses the strongest inspector that is the same as or weaker than the inspector of the currently expanding macro’s module and the source syntax object’s inspector.

Compiled code from a ".zo" file is inherently untrustworthy, unfortunately, since it can be synthesized by means other than compile. When compiled code is written to a ".zo" file, syntax-object constants within the compiled code lose their inspectors. All syntax-object constants within compiled code acquire the enclosing module’s declaration-time inspector when the code is loaded.

top ← prev up next →