REBOL 3.0

Comments on: 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

Comments:

Oldes
7-Oct-2006 6:13:51
here is a small typo, in the example should be just:
probe append body [* 2]
obj/f
as the print is already part of the function (so the second print will throw an error (print is missing its value argument):)
Oldes
7-Oct-2006 6:19:55
Will be available some function which would return the context to which is a value bounded?
oldes
7-Oct-2006 6:29:40
Anyway, I don't remember I ever used such a coding and don't know how many people are using such a "funny and cool" scripting. I just woried if it will be possible to modify some parts of Rebol's code if it's needed. For example for my cookies-daemon I'm patching the http handler using:
system/schemes/http/handler: make system/schemes/http/handler [...]
Which could be probably patched the same way how you described. Will it be still possible to do such a patches somehow? (I know that the system is going to disappear, so there must be some changes)
Ladislav
7-Oct-2006 11:02:32
Because that change would make some of my HOF impossible, I would demand a compensation ;-)
Anton Rolls
7-Oct-2006 12:29:20
Oldes, you don't mean to determine the context of a word, as we can do now ? eg: >> ctx: context [a: 1] >> probe do bind [self] in ctx 'a make object! [ a: 1 ]
Anton Rolls
7-Oct-2006 12:30:58
Ladislav, which higher order functions are affected (and how much do you use those ones now ? ;)
Gregg Irwin
7-Oct-2006 12:42:19
It would be good to see examples of how to implement things like Ladislav's HOF, Maarten's DbC, or any other kind of "aspect weaving". I know AOP is a buzzword, and I think it makes a simple idea too complex, but trace/function inundates you, so it can be nice to "hook" just a specific list of funcs or objects for tracing or other behavior. It may be that wrappers will work in most cases.
Carl Sassenrath
7-Oct-2006 13:54:44
Oldes: thanks - typo fixed.

Ladislav: Lol! You do amazing things, but you were also the first person to mention this "feature" and that it would be problematic. (We should look at HOF a bit more, to determine if there is a direct way to support them.)

Gregg: As it turns out, these "restrictions" are those required for secure modules. But, there can always be special "disable security" options, such as those that already exist. Useful for debugging, as you point out.

A good example... there exists a "root context" that is hidden from all programs but it contains values such as the run-time evaluation stack itself (as a block), and a lot more.

Carl Sassenrath
7-Oct-2006 14:01:04
Oldes: and, yes... there will be a way to make such patches. With valid security certification, you can certainly enter any existing context and make changes.

For example, if a module has been signed, a valid equivalent signature may be required for patching it. Of course, you can also use SECURE NONE style method.

(Some of you may be noticing that we are walking right along the edge of a capabilities architecture.... which would be quite nice if we found a way to do... but may need to be put off to 3.1 or later.)

Ladislav
8-Oct-2006 11:22:12
Anton: it is not that bad. Actually, only the TFUNC will be impossible to implement (but that will be solved natively, I suppose), all other higher order functions are unaffected.
Anton Rolls
11-Oct-2006 4:44:29
Ladislav, that is good. And as Carl says, we could still patch function bodies directly by disabling security in some way.

Post a Comment:

You can post a comment here. Keep it on-topic.

Name:

Blog id:

R3-0049


Comment:


 Note: HTML tags allowed for: b i u li ol ul font span div a p br pre tt blockquote
 
 

This is a technical blog related to the above topic. We reserve the right to remove comments that are off-topic, irrelevant links, advertisements, spams, personal attacks, politics, religion, etc.

REBOL 3.0
Updated 26-Mar-2017 - Edit - Copyright REBOL Technologies - REBOL.net