From: kangax on
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
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
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
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