Prev: How do I get keys from an associative array?
Next: instructor's solutions manual for Basic Electromagnetics with Applications by Nannapaneni Narayana Rao
From: kangax on 22 Feb 2010 23:50 On 2/22/10 12:03 PM, Lasse Reichstein Nielsen wrote: > kangax<kangax(a)gmail.com> writes: > >> If I'm reading spec correctly, one of the ways to get global object >> from within _any_ code in ES5 is by using indirect call to eval. > > Not if there is another variable called "eval" in scope. But, AIUI, you can't have another variable named eval in strict mode :) From 12.2.1: 'It is a SyntaxError if a *VariableDeclaration* or *VariableDeclarationNoIn* occurs within strict code and its Identifier is either "eval" or "arguments".' And from 13.1: 'It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs within a *FormalParameterList* of a strict mode FunctionDeclaration or FunctionExpression.' and: 'It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the Identifier of a strict mode *FunctionDeclaration* or *FunctionExpression*.' (emphasis mine) > If you are certain to have access to "eval" on the global object, you > are pretty close to haveing the global object itself. > > Another approach is Function("return this")(), but Function may be That was my first thought as well, but from what I can see, this won't "work". It looks like `Function('return this')()` won't give you a global object. 1) Function('return this')() is a function call. 2) Algorithm for function call (11.2.3) explains what the value of `this` should be, when invoking [[Call]] of an object. 3) Step 7 of 11.2.3 says that if Type(ref) is not Reference, `thisValue` is set to `undefined`. `Function('return this')` doesn't evaluate to a Reference, so we end up with: <function object>.[[Call]](thisValue = undefined, argList = ...) 4) finally, function code is entered (10.4.3) and ThisBinding is set to thisValue passed to [[Call]] (step 1). `Function('return this')()` should therefore return `undefined`, even though function's scope is set to global environment. In this particular case, it's not much different than calling `(function(){ return this; })()`. Or did I miss something? [...] -- kangax
From: Lasse Reichstein Nielsen on 23 Feb 2010 02:27 kangax <kangax(a)gmail.com> writes: > On 2/22/10 12:03 PM, Lasse Reichstein Nielsen wrote: >> kangax<kangax(a)gmail.com> writes: >> >>> If I'm reading spec correctly, one of the ways to get global object >>> from within _any_ code in ES5 is by using indirect call to eval. >> >> Not if there is another variable called "eval" in scope. > > But, AIUI, you can't have another variable named eval in strict mode :) No, but you can create a shadowing binding before entering strict mode, e.g., // Non-strict context. function myEval(s) { "use strict"; return eval(s); } function shadower() { var eval = myEval; return function context(){ "use strict"; << your code inserted here >> }(); } shadower(); >> If you are certain to have access to "eval" on the global object, you >> are pretty close to haveing the global object itself. >> >> Another approach is Function("return this")(), but Function may be > > That was my first thought as well, but from what I can see, this won't > "work". It looks like `Function('return this')()` won't give you a > global object. True, my mistake. The function's scope will be the global environment, but it will create a new scope when it's called, just as any other function. > Or did I miss something? No, not as far as I can see. However, the Function constructor can create non-strict functions in a strict environment, so this should work: var global = Function("return function(){return this;}();")(); A determined jailer will be able to prevent that too, by changing the binding of Function and Function.prototype.constructor: var myFunction = function(oldFunction) { var myFunction = function Function(args) { var arr = Array.prototype.slice.call(args, 0, args.length); arr[arr.length-1] = '"use strict";\n' + arr[arr.length-1]; return oldFunction.apply(null, arr); }; Function.prototype.constructor = myFunction; return myFunction; }(Function); function myEval(s) { "use strict"; return eval(s); } function shadower() { var eval = myEval; var Function = myFunction; return function() { "use strict"; << Your code, in jail >> }(); } I'm sure there are still holes in this (e.g., setTimeout with string argument), but the idea is to prevent you from getting access to running non-strict code in any way. That will also prevent you from getting direct access to the global object. You will actually need to shadow access to ANY non-frozen object on the global object - because if "foo" refers to an property of the global object, then foo.bar = function() { return this; } var global = foo.bar(); would work. Strict mode is build so that you can't access strict mode variables from non-strict code. You are still allowed to create non-strict code, but only as if the code was running in the global environment. /L -- Lasse Reichstein Holst Nielsen 'Javascript frameworks is a disruptive technology'
From: Dr J R Stockton on 25 Feb 2010 15:48 In comp.lang.javascript message <f249e211-5103-4933-8fc2-92740e661ba7(a)t3 1g2000prh.googlegroups.com>, Sat, 20 Feb 2010 18:37:37, Stoyan <ssttoo(a)gmail.com> posted: >Since JS is everywhere (client, server, desktop...), it makes sense to >think how to write code that could run in environments other than the >one originally in mind. Perhaps it's not a good idea to use `window` >when the code could possibly run in environment that has no idea what >`window` is. Evidently you cannot use any of the special properties of "window". Do you really [always] need to access *THE* Global Object, or might it be [sometimes] sufficient to create one with a known name, perhaps by var glObj , and use it instead? -- (c) John Stockton, nr London, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME. Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links; Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc. No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.
From: kangax on 28 Feb 2010 22:13
On 2/23/10 2:27 AM, Lasse Reichstein Nielsen wrote: > kangax<kangax(a)gmail.com> writes: > >> On 2/22/10 12:03 PM, Lasse Reichstein Nielsen wrote: >>> kangax<kangax(a)gmail.com> writes: >>> >>>> If I'm reading spec correctly, one of the ways to get global object >>>> from within _any_ code in ES5 is by using indirect call to eval. >>> >>> Not if there is another variable called "eval" in scope. >> >> But, AIUI, you can't have another variable named eval in strict mode :) > > No, but you can create a shadowing binding before entering strict mode, e.g., > > // Non-strict context. > function myEval(s) { "use strict"; return eval(s); } > function shadower() { > var eval = myEval; > return function context(){ > "use strict"; > << your code inserted here>> > }(); > } > shadower(); Ah, yes. `eval` might indeed resolve to something other than built-in `eval` function. > >>> If you are certain to have access to "eval" on the global object, you >>> are pretty close to haveing the global object itself. >>> >>> Another approach is Function("return this")(), but Function may be >> >> That was my first thought as well, but from what I can see, this won't >> "work". It looks like `Function('return this')()` won't give you a >> global object. > > True, my mistake. The function's scope will be the global environment, > but it will create a new scope when it's called, just as any other > function. > >> Or did I miss something? > > No, not as far as I can see. > > > However, the Function constructor can create non-strict functions in > a strict environment, so this should work: > > var global = Function("return function(){return this;}();")(); I'm afraid this still returns `undefined`. From what I can see, non-reference function call � which (function(){})() is � always sets thisValue to `undefined`. Even in non-strict mode. However, (function(){ return this; }).call(null) should actually return global object, when not in strict mode (null/undefined are coerced to global, as per 10.4.3). So I guess we can change it to this "little guy": var global = Function('return (function(){return this;}).call(null)')(); But I'm not fully sure about it. ES5 specs are even more convoluted than ES3 ones :) > > A determined jailer will be able to prevent that too, by changing > the binding of Function and Function.prototype.constructor: > > var myFunction = function(oldFunction) { > var myFunction = function Function(args) { > var arr = Array.prototype.slice.call(args, 0, args.length); > arr[arr.length-1] = '"use strict";\n' + arr[arr.length-1]; > return oldFunction.apply(null, arr); > }; > Function.prototype.constructor = myFunction; > return myFunction; > }(Function); > function myEval(s) { "use strict"; return eval(s); } > function shadower() { > var eval = myEval; > var Function = myFunction; > return function() { > "use strict"; > << Your code, in jail>> > }(); > } Interesting. But yes, in ES3 we could get away with `(function(){return this;})()` which didn't involve identifiers, and so couldn't be shadowed/intercepted. Not so in ES5, as it appears (which was probably committee intention in the first place). > > > I'm sure there are still holes in this (e.g., setTimeout with string > argument), but the idea is to prevent you from getting access to > running non-strict code in any way. That will also prevent you from > getting direct access to the global object. Yes. > > You will actually need to shadow access to ANY non-frozen object on > the global object - because if "foo" refers to an property of the > global object, then You mean if `foo` refers to global object? <global>.foo.bar() would invoke function with `this` referencing <global>.foo. > foo.bar = function() { return this; } > var global = foo.bar(); > would work. [...] -- kangax |