REBOL3 tracker
  0.9.12 beta
Ticket #0001744 User: anonymous

Project:



rss
TypeWish Statusreviewed Date4-Nov-2010 07:42
Versionalpha 110 CategoryNative Submitted byBrianH
PlatformAll Severityminor Prioritynormal

Summary Have CATCH /name consider name bindings
Description THROW/name and CATCH/name are rarely used, because there's not much difference between them and THROW and CATCH in practice (partly because of #1518). We should make them more useful, so there will be more cases where they can come in handy. A good way to improve CATCH/name is for it to change its word comparison from EQUAL? to EQUIV?, considering context as well.

If we make CATCH/name pay attention to the context of its word argument and only catch when the word thrown by THROW/name has the same context, then we can use CATCH/name for secure non-local control flow. The problem that /name has now when making control flow functions is that it can be spoofed by throwing the name it is expecting. If you need a reference to a particular context in order to throw to it, security can be assured by controlling the visibility of the context, which BODY-OF does nicely. Simply knowing the name won't be enough.

This would also help when mixing code from different sources and modules. If CATCH/name only catches a particular context, throws and catches from different contexts can be mixed safely even if there are name conflicts, which are almost inevitable in large projects.

Unbound words would only be caught if unbound words are thrown. This would be a good way to work around the context-based security restrictions when they don't matter.

THROW/name would not need to be changed at all.

This proposal, along with #1518 and #1520, would help to change THROW/name and CATCH/name into a powerful tool for more advanced developers. This would be a big improvement over not being used at all.

This proposal was suggested by Ladislav in AltME. Most of the concerns expressed above were paraphrased from his remarks there.
Example code

			

Assigned ton/a Fixed in- Last Update12-Nov-2010 10:14


Comments
(0002785)
Ladislav
4-Nov-2010 09:25

My main concern about CATCH/NAME is different. I am afraid it won't be used exactly like before, since:

* the CATCH/NAME call is nonnegligibly longer than the CATCH call, and the improvements may even worsen this
* the THROW/NAME call is nonnegligibly longer than the THROW call (and, again, improvements don't help with that issue)
* due to the above reasons, it is likely that anybody encapsulating those in a REBOL function to get something more concise (see e.g. my "cheap CONTINUE for R2" workaround at http://www.rebol.org/view-script.r?script=c-aware.r ) can demonstrably do without the CATCH/NAME THROW/NAME pair, using just CATCH and THROW
* last but not least, the number of users of the CATCH/NAME THROW/NAME pair is lower than 3, in my opinion

To me, the CATCH/NAME THROW/NAME pair just looks as a "cheap replacement" for a definitional RETURN, or definitional THROW "mechanism".
(0002786)
BrianH
4-Nov-2010 10:14

Except the local part. We already have local THROW and RETURN. What we don't have is a non-local THROW that can skip over a lot of intervening catches, whether they have /name specified or not.

The *only* reason THROW/name is of local use only right now is #1518. There are only a few people who need to catch all throws, named or not, but there are *many* people who need to bypass a lot of levels of code, including levels they didn't write themselves.

CATCH/name true (#1520) restores the R2 CATCH behavior for the 2 or 3 people who need it. Those people are doing important stuff like making test harnesses and robust frameworks, so their work needs to be supported.

But most people can't use THROW/name at all for what it would be best at because #1518 almost completely disables THROW/name, jailing it so thoroughly to the local level that even experienced REBOL developers have trouble thinking of THROW/name as being anything other than a "cheap replacement" for a "local RETURN", or "local THROW" "mechanism".

The proposal in this ticket will help deal with the other, less important problem with using THROW/name non-locally: name conflicts. And it also has the advantage of allowing users to cut down on spoofing, allowing CATCH/name and THROW/name to be useful for sandboxing functions, or other situations where you might be running hostile code. Without the security advantages, this would only be trivial compared to #1518.
(0002807)
BrianH
5-Nov-2010 21:32

Please use a different term than "local" for that quality then, like "targeted". We are in the middle of a discussion where the *other* meaning of "local" is the point of contention and the huge problem we are dealing with. Let's reserve the word "local" for meaning *called from* nearby code, rather than *defined in* nearby code.

This ticket enhances the power of when the code containing the THROW/name is defined in code that is near to the code that the CATCH/name is defined in. The reason that this ticket enhances such code *only* is because that is the most likely way for the name thrown to be bound to the same context without having to explicitly pass the word or a reference to the context from the code containing the CATCH/name to the code containing the THROW/name. The main reason it is an enhancement is security: You can control the range of code that can get a reference to a context (the "visibility" of that context), while it is much more difficult to control who is aware of the spelling of a name. This means that CATCH/name would be harder to hack - useful for sandboxing and such. As a side benefit, it also makes it easier to mix code that is created by different people in different files to be used in the same control flow without accidental name conflicts - useful for PITL.

The security advantage would just as easily be served by a CATCH /same option, as it is the feature that matters. The PITL advantage can only be served by making it the default behavior. There is a tradeoff of making it more difficult to explicitly THROW/name from code that is *called* from somewhere else, but that can be easily worked around by providing them with (now unspoofable) wrapper functions that are defined locally, or passing the calling code a word to throw to.

However, none of this matters until we deal with the other problem (#1518 and #1520): Regardless of where the code is defined, THROW/name can only be *used* locally (meaning, in a limited, controlled flow of code) because CATCH *by default* catches stuff that is none of its business to catch, including all THROW/name calls. This means that there is a dam in the middle of the regular control flow, so you can't use THROW/name if the control flow goes through code written by other people. And most people who aren't familiar with this problem would quite sensibly expect THROW/name to work, and then stop using it when it becomes clear that this bug in CATCH makes THROW/name no different from THROW.

Tickets #1518 and #1520 are not a proposal to get rid of CATCH's current behavior; they are a proposal to change the default. And that change is critical, because the default now is something useful to only a few people in the world - you don't see this because *you* are one of those few people. Most people need a *better* default. And #1520 is for those rare circumstances where someone actually needs to catch everything, which most people don't need to or want to do.
(0002850)
maxim
12-Nov-2010 09:54

as a developer of *very* large REBOL projects for years it occured only recently to me that I've NEVER used THROW/CATCH.

I've always been one of the rare PITL REBOLers and such a realization is worthy of some consideration, so I started to think about why I'd never used them.

It occurred to me that the "dam" described above *IS* the reason. the current system is practically useless in practice.

I also don't recall *ever* reading code that uses throw. Another big realization.
(0002851)
maxim
12-Nov-2010 10:01

I want to add my own little extension to the proposal.

have #issue act exactly like unbound words. They stand out very well in code and would nicely separate bound/unbound THROW usage.

for many of my use cases, I'd prefer unbound throws simply because in some of my systems, I am using classed based object abstraction. The reasons are many but the main one is simply because it is very frugal in terms of memory and speed. in cases like liquid, the context of code creation and code execution are always different, and in fact the execution shares the same context for many nodes since its being done in class, but the setup is differentiated since its being done in the instance.

for this reason, I am forced to use unbound words, but actually generating unbound words is a complex process, so using #issues as such would simplify my life, since I'd really like to use throw a lot more.
(0002854)
BrianH
12-Nov-2010 10:14

UNBIND word. It's not a complex process in R3, and UNBIND is on the top priority list for R2 backports.

The reason why it's on that list is because for R2 you are right, Maxim. I have been putting off writing a mezzanine version of UNBIND for R2 because the code required would be too intimidating. Do you want to give it a shot?

Date User Field Action Change
23-Mar-2013 03:28 Ladislav Comment : 0002785 Modified -
14-Nov-2010 11:47 Ladislav Comment : 0002788 Removed -
14-Nov-2010 11:47 Ladislav Comment : 0002785 Modified -
12-Nov-2010 19:15 BrianH Comment : 0002854 Modified -
12-Nov-2010 10:14 BrianH Comment : 0002854 Added -
12-Nov-2010 10:01 maxim Comment : 0002851 Added -
12-Nov-2010 09:54 maxim Comment : 0002850 Added -
5-Nov-2010 21:39 BrianH Comment : 0002807 Modified -
5-Nov-2010 21:32 BrianH Comment : 0002807 Added -
5-Nov-2010 00:07 carl Status Modified submitted => reviewed
4-Nov-2010 16:36 Ladislav Comment : 0002788 Modified -
4-Nov-2010 16:31 Ladislav Comment : 0002788 Modified -
4-Nov-2010 16:29 Ladislav Comment : 0002788 Added -
4-Nov-2010 10:31 BrianH Description Modified -
4-Nov-2010 10:27 BrianH Comment : 0002786 Modified -
4-Nov-2010 10:21 BrianH Comment : 0002786 Modified -
4-Nov-2010 10:20 BrianH Description Modified -
4-Nov-2010 10:14 BrianH Comment : 0002786 Added -
4-Nov-2010 09:53 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:50 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:45 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:39 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:35 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:32 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:31 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:29 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:26 Ladislav Comment : 0002785 Modified -
4-Nov-2010 09:25 Ladislav Comment : 0002785 Added -
4-Nov-2010 08:19 BrianH Description Modified -
4-Nov-2010 07:48 BrianH Description Modified -
4-Nov-2010 07:42 BrianH Ticket Added -