World: r3wp
[!REBOL3]
older newer | first last |
Geomol 26-May-2011 [8947] | wouldn't *we* ... |
Maxim 26-May-2011 [8948] | yep, we can build our own function builders but again, this means we do it ourself. ;-) would just be nice if one refinement where reserved for inaccessible words.... which is what /local has been used for for 15 years (even though its been an illusion ;-) |
Geomol 26-May-2011 [8949x3] | Can you give an example of a function, where it's a problem, locals are not really local? |
Maybe a function, where the local var is set, if some condition is fulfilled, and then the local is returned in the end, being NONE, if it wan't set. Is that an example of such a problem function? | |
*wasn't* | |
Maxim 26-May-2011 [8952] | Here is an example of a function hi-jacking. it is something that can commonly be seen in larger apps, where some locals are only used conditionally. in this case, the original function is hijacked and we could really do nasty things here. -------------------------------------------------------------------- rebol [] f: func [a [string! block!] /local str][ ; uncomment to make the function safe ; str: none if block? a [ str: mold a ] print any [str a] ] evil-func: func [a ][ ; do something evil here print "EVIL!" head insert a " >:-P >>> " ] f/local "Print occurs as if nothing is wrong" :evil-func ask "!" |
Geomol 26-May-2011 [8953] | Good example! :) Houston, we have a problem! |
Maxim 26-May-2011 [8954] | using this trick we can get internal function values even if we cannot change function bodies anymore. my point is not that this can be done with any arguments. its just that the way we all use /locals, we don't include argument protection. so I think its just a good thing to allow this functionality by default in the language, since we all use /locals as if it where already there. |
Kaj 26-May-2011 [8955] | What about the full FUNCTION form? |
Maxim 26-May-2011 [8956] | IIRC, its just a stub which creates a 'FUNC spec. |
Kaj 26-May-2011 [8957] | I remember it the other way around |
Maxim 26-May-2011 [8958x2] | on make function! , the argument spec is just one block, not two. |
unless it's changed while I wasn't looking ;-)( | |
Kaj 26-May-2011 [8960] | Hm, yes, that makes the issue extra deceptive. FUNCTION looks like it has real locals |
Ladislav 27-May-2011 [8961x2] | FUNCTION was the other way around, Kaj, but *long* ago |
R1 | |
Geomol 27-May-2011 [8963] | Maxim, in your example, the user has access to the function f, can call it direcly. Let's say, we couldn't give the /local refinement, then I could just write: f evil-func "Print occurs as if nothing is wrong" Why is it a problem, we can give the /local refinement? Isn't it false security, if it is changed, so we can't call with /local ? |
Kaj 27-May-2011 [8964x2] | Ah, a scheme engine leftover :-) |
Carl reacted to its complexity with extreme simplicity, so this one may have been one bridge too far | |
onetom 27-May-2011 [8966x2] | i wish we would live in a world where u shouldn't be concerned about this kind of security issues :D |
this concept is sooo lovely, that u can even build such a fundamental feature as local variable via the already existing specs dialect, my heart hurts to see we can't keep this virgin beauty and have to sacrifice it on the altar of security... | |
Kaj 27-May-2011 [8968] | Yeah, I also thought it elegant when I heard about it, but on the other hand it violates the principle of least surprise |
BrianH 27-May-2011 [8969] | REBOL is too weird compared to other programming languages for it to really be possible or even desirable to avoid surprise :) |
Kaj 27-May-2011 [8970] | I know, but this one would be surprising in any language |
BrianH 27-May-2011 [8971] | Not any language - I think you are underestimating the variety in languages. Some don't have local variables at all, for instance. |
Kaj 27-May-2011 [8972x2] | Doesn't matter. The surprise is about local variables being initialisable from the outside |
Local variables are by definition about encapsulation, and this is not encapsulation | |
BrianH 27-May-2011 [8974x2] | The surprise being that there aren't really any local variables, just arguments which might be optional. There was a proposal to make there be non-argument local variables in R3, and I wouldn't be opposed to this, but "least surprise" isn't a good enough argument for why in such an inherently surprising language as REBOL. I also wouldn't be opposed to having FUNCT add an ASSERT/type [local none!] to the beginning of the code block of every function it generates. |
That last trick would be difficult to do safely though, at least as FUNCT is used in the mezzanine generation process. Mezzanines are generated with FUNCT but saved with MOLD into the form where they will be loaded at runtime. This means that FUNCT can't generate code that has inline function or datatype values in it, since they won't mold properly. Unless you inline the references to ASSERT and NONE!, those words couldn't be used as function parameters or local variables in the generated functions. Tradeoffs, I guess. | |
Kaj 27-May-2011 [8976] | I hereby propose to rename the /local refinement to /not-local |
Geomol 27-May-2011 [8977x2] | :-D |
I can't figure out, if the /local behaviour is a real problem, or just one in our minds. | |
Kaj 27-May-2011 [8979] | It has become a problem, now that people know it can be abused :-) |
Geomol 27-May-2011 [8980x2] | But who can abuse it? Just ourselves or outside hackers in a web application? |
If it's just the programmer, who has full control over the functions anyway, then I see no problem. | |
Kaj 27-May-2011 [8982x2] | Yeah, that's the criterium. You still need to be able to inject code |
However, if someone gets a sandbox, every function made available can now be probed for code injection through this hole | |
Sunanda 27-May-2011 [8984] | For better local variables, you can use USE. But it's a bit clunky. f: func [a b][use [c] [c: a + b c]] ;; 'c is local to the function, and not easily/obviously affected by anything outside |
BrianH 28-May-2011 [8985x2] | It's really not any more of a problem for /local than it is for any other function option or argument, since the real problem is that the techniques for code injection have been revealed. Fortunately, so have the methods for avoiding or counteracting it: APPLY, type checking, get-words, or wrapping expressions in parens or putting them at the end of blocks to make sure that they can't get access to modifiable values later on in the block. |
Sunanda, agreed, and also about it being clunky, particularly because USE has both COPY/deep and BIND/copy overhead in R3. ASSERT/type [local none!] is still the most efficient method. | |
Robert 30-May-2011 [8987] | Has anyone tried to use extensions in R3 OSX? Do these work? |
Andreas 30-May-2011 [8988] | Yes, they work. (Only did some basic testing, though.) |
Robert 30-May-2011 [8989] | Callback as well then? |
Andreas 30-May-2011 [8990x2] | Didn't try. |
Yes, my basic callback test works fine. | |
Robert 31-May-2011 [8992] | Perfect. |
Geomol 6-Jun-2011 [8993] | In R3, BACK doens't behave as SKIP ... -1. >> s: [1 2 3 4] == [1 2 3 4] >> t: skip s 3 == [4] >> remove/part s 3 == [4] Now it takes 3 x BACK t to see anything: >> back back back t == [4] while it only takes 2 x skip -1: >> skip skip t -1 -1 == [4] I'm not sure, if this is known or desired behaviour. |
BrianH 6-Jun-2011 [8994x2] | In R2, indexes are constrained to the bounds of the series they reference, so if you shorten the series you lose your position. In R3 your position is preserved for most of the standard operations, just in case you add back to the series later. The operations that can't possibly work for those out-of-bounds references trigger errors (mostly modifying operations), and the ones that could work if you consider series bounds to be an implementation detail and out-of-bounds values to be just not there return none (data access functions). SKIP is an exception, afaik, to allow you to sync up with the bounds - useful, but I don't remember whether it was intentional or a happy accident. >> a: "abc" == "abc" >> c: skip a 2 == "c" >> remove/part a 2 == "c" >> index? skip c 0 == 2 >> index? c == 3 |
The point of this in R3 was to rebalance the behavior in favor of not triggering as many errors when they aren't useful. The policy in R3 is that errors should be your friends, and that means triggering errors where they help in general, preferably informative errors, and not triggering errors where they aren't generally helpful. The conceptual definition of series was changed in R3 to make bounds less hard so as to trigger fewer errors; out-of-bounds positions are now considered to have no values in them, rather than not being there, under most circumstances when you can get away with it - you can't necessarily get away with it for modifying operations. This change was based on analysis of common code patterns, and considering that error catching is expensive in most programming languages, including REBOL; none checking is much less expensive. In the cases where explicit bounds checking is necessary, that isn't expensive to add to your code, not nearly as expensive as the bounds checking required in code in R2 that isn't required at all in R3. | |
onetom 6-Jun-2011 [8996] | BrianH: that's a beautiful description. it should be part of the R3/Concepts document. can we just dump it to there? (i don't have write privileges yet) |
older newer | first last |