metaeducation / rebol-issues

6 stars 1 forks source link

Loophole to add words to modules after creation -- uses BIND? and SELF #1555

Closed rebolbot closed 8 years ago

rebolbot commented 14 years ago

Submitted by: meijeru

This is a revival of part of the discussion in #896. It is possible (if not desirable) to extend the body of a module after its creation and binding, adding new set-words via the object yielded by BIND? Altough BrianH said in the comments to the earlier ticket that these words would not be available to the module code, this is not true thanks to SELF.

>> m: module [][a: 1 f: func [][get in self 'b]]
>> m/f
== none ;; b does not exist
>> o: bind? in m 'a
== make object! [
    a: 1
    f: make function! [[][get in self 'b]]
]
>> extend o 'b 2
== 2 ;; add field to context
>> m/b
== 2 ;; it shows up in the module
>> m/f
== 2 ;; and it can be used!!!!

CC - Data [ Version: alpha 97 Type: Issue Platform: All Category: Security Reproduce: Always Fixed-in:none ]

rebolbot commented 14 years ago

Submitted by: meijeru

We are obviously in the semantics area here; I extended the "internal context object" (which I presume is physically identical to the body) with a simple integer just to prove my point. It could have been a more complicated value, and let's not forget that in REBOL all data is code... Also, the piece of code GET IN SELF 'B could have used a variable instead of a lit-word 'B!

Let me be clear: I do not put this forward as a programming method, but it could be a security loophole, couldn't it?

rebolbot commented 14 years ago

Submitted by: BrianH

It is hard to make into a security hole if the module code is written securely. However, module security is currently incomplete, waiting on the PROTECT and UNPROTECT tickets #1014, #1015, #1141, #1142 and #1143. Until those bugs are fixed and enhancements made, we can't make modules truly secure.

The question is whether we really want to make an exception that would allow internal contexts of modules to be used as data structures? Do gotchas like the above (mostly in R2-style code since R3 has get-paths and GET path!) outweigh the potential benefits? That should be decided.

Btw, the internal context object is only rarely similar to the module body, only in trivial cases. For most real world cases it isn't close.

rebolbot commented 14 years ago

Submitted by: meijeru

As far as I understand, the context of a module (as yielded by BIND?) is an object composed of the first level set-words of the module body bound to the values they have. How can this be different from the module-body except as far as typing is concerned?

I would imagine that BODY-OF M == BODY-OF BIND? IN M 'A

rebolbot commented 14 years ago

Submitted by: BrianH

Object and module specs are made up of code that initializes them. Only in trivial circumstances does that code resemble pairs of set-words and values. BODY-OF doesn't really return the body of either an object or a module - that information is no longer referenced by objects and modules after their initialization. Instead, it is overloaded to return a block of word/value pairs, the result of that initialization code but not the code itself, or even a copy of it.

Don't let the name of BODY-OF fool you: It only returns (an unbound copy of) the body of functions and closures. For the other types it fakes it.

rebolbot commented 14 years ago

Submitted by: meijeru

I still have some difficulty undestanding all this. In part this may be because you refer to implementation details that I can't know because they cannot be divulged, and because of terminology (perhaps related to these implementation details).

When you say "code" do you mean e.g. C-code? And is the context object also faked (or at least created by BIND? on demand)?

rebolbot commented 14 years ago

Submitted by: BrianH

I mean REBOL code (of the DO dialect). The closest thing to a function body (which is what BODY-OF was named for) that an object has is the block passed to MAKE object!, which is treated as REBOL code. Which is also the closest thing an object has to a spec, for now, though modules actually have specs (the header). There is no CODE-OF function because the resulting object or module doesn't keep a reference to that code block after the object or module is created.

So the BODY-OF function generates a block of set-word/value pairs when applied to modules or objects, since that is the most useful thing it can return. But that is not the code of the object or module; the code is lost unless you keep a reference to it yourself.

The module's context object isn't faked, it's an internal reference.

rebolbot commented 14 years ago

Submitted by: meijeru

I understand the notion of "code" now; it is the fact that BODY-OF CONTEXT [A: 1 + 2] shows up as [A: 3]. The body block of a module is operated on by DO inside SYSTEM/INTRINSIC/MAKE-MODULE, I notice, just before the result is returned. But that does not take away that the correspondence between the module's words and their values, which is what I would call the body, during its lifetime, is none other than the context object -- what else could it be? And since one can operate on the context object, one can indirectly operate on the module body (in the sense of the actual words and values of the module during its lifetime). It is true that this operation, e.g. the extension I showed, is not impacting on the result of IMPORT if it takes place after IMPORT has been invoked. But modules are not only used via IMPORT, the documentation mentions explicitly that you can use them as a sort of object as well.

rebolbot commented 14 years ago

Submitted by: BrianH

I also think it is reasonable to prohibit extension of the module's internal context object in MAKE-MODULE (especially since that is REBOL code that can be replaced at runtime if need be) - the comments were just a semantic note. We just can't do it until the protection bugs listed above are fixed.

rebolbot commented 14 years ago

Submitted by: Carl

In R3 the purpose of a module is to provide an "official" mechanism of grouping related code and data. It is a wrapper for writing better "code in the large". In R2, we used the unofficial mechanism: objects. In R3, modules make this mechanism official, and we've added some "helpers" to make it more generally useful.

There is no claim at this time that R3 modules are secure or protected in any way from other code. That would be a separate project, and it is not included in 3.0.0.

With that in mind, this ticket is not a bug and is therefore dismissed.