REBOL 3.0

The Problem with Function Reflection

Carl Sassenrath, CTO
REBOL Technologies
6-Oct-2006 21:44 GMT

Article #0049
Main page || Index || Prior Article [0048] || Next Article [0050] || 11 Comments || Send feedback

As you know, REBOL provides a high level of reflection for most constructs. For example, if you define a function:

buy: func ["Purchase stock" stock [string!] price [money!]] [
    repend stocks [stock price]
]

You can obtain the specification for the buy function with:

probe third :buy
["Purchase stock" stock [string!] price [money!]]

and its body with:

probe second :buy
[
    repend stocks [stock price]
]

This is quite useful for help-related functions, editing systems, and implementing remote procedure call (RPC) or web-service middleware.

The problem

Unfortunately, REBOL V2 also provides "undocumented" semantics that are problematic. Here is an example:

obj: make object! [
    a: 10
    f: func [] [print a]
]
body: second get in obj 'f
probe body
[print a]
print get second body
10
do body
10

The body reflector (second) obtains more than just the symbolic representation of the function, it returns the actual block, including all levels of its bindings. That result allows us to "peek" inside the context of the obj object, and in the above example we print the value 10 that was reflectively fetched from that context.

In addition, since the body block is returned by reference (not a copy), we can directly modify the function:

probe append body [* 2]
[print a * 2]
obj/f
20

While this may be fun and cool, it creates a big problem for REBOL V3 because we lose one of the primary benefits of modules: true encapsulation of module internals.

Such a behavior would create a security hole in the new module system planned for REBOL V3. For example, if a module defines a private variable for storing a password string:

password: "lober57"

the above reflective behavior would allow access, either directly using a bound word reference, or indirectly by modifying a function's body. Either way, the result is unacceptable.

Solution for function reflection

The obvious solution to this problem is that function reflection should be modified to return an unbound copy of the functions blocks. And, V3 will work that way. But this change will have consequences for some types of code.

But, there's more to it...

It should also be noted that the ability to handle contexts as first class values is an essential part of REBOL, and there are many ways to "accidentally" expose a context. Module programmers of secure subsystems need to be careful when returning blocks or other values that may contain references into the module's context such as bound words.

In addition, it may be possible to restrict the bind function to prevent binding directly to module contexts unless the caller can prove that it has the required level of trust within the context itself.

I'm sure we will be visiting this subject in more detail as V3 becomes available for alpha testing.

11 Comments

REBOL 3.0
Updated 19-Dec-2024 - Edit - Copyright REBOL Technologies - REBOL.net