views:

151

answers:

3

This code outputs D. The question is HOW?

alert([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[+!+[]]](+[]+[+[]])[+!+[]]);

I understand that ![] is evaluated to false or 0 and so on, but how does it execute? And how can I convert this to something humans can understand and not only Jon Skeet?

Can someone break some piece of this code and explain me what's happening?

+8  A: 

Well, evaluating the expression in parts, at the end it is equivalent to:

[]['sort']['call']()["btoa"]("00")[1]; // "D"

Which can be simplified to :

btoa("00")[1]; // "D"

How you can "decode it"?

Simply examine the operators used, for example, we can see at first that an array literal is used, then several bracket notation property accesses are done, and a couple of invocations.

How does it work?

The trick is to chain multiple type conversions, for example, to get the f letter:

(![]+[])[+[]]

If we examine the first part, in parentheses, ![]+[], we see a boolean negation, which will return false because an array object is always truthy, and then a concatenation.

That produces the string "false", then, the second part, we see a brackets applied to that string, to access a character, and the expression +[], which results in 0.

+[] gives zero because the Array's toString method returns an empty string, for an empty array like that one, and an empty string produces to zero when it is converted to number (the unary + operator in this example).

There are just tricks like that, things that produce a string, such "true", "false", "null", "undefined", etc... and more tricks to get the numerically.

For example to get a number -to access a character-, they use again cryptic type conversion:

+[];            // 0, equivalent to +""
+!+[];          // 1, equivalent to +true
!+[]+!+[];      // 2, equivalent to +true+true
!+[]+!+[]+!+[]; // 3, equivalent to +true+true+true
CMS
How did you get to it? Is there some tool to convert this code?
BrunoLM
try the different parts in an interactive javascript shell (built into chrome and ie8, and can be obtained for firefox (the addon firebug) or you can install node.js or many other tools.
ormuriauga
Thank you. I get how it works now. But I'm still wondering how did you solve it so fast :P
BrunoLM
A: 

![] is false. ![] + [] evaluates to 'false'. +[] is 0 so !+[] is true, etc. javascript is very strange with its implied type conversions

ormuriauga
Please refrain from using swear words in your answers, we're trying to keep SO for General Audiences without Parental Guidance.
Marko
ok, sorry. I am not from a country where we think in those terms. fixed it
ormuriauga
+2  A: 

It does some tricks with the javascript type conversions. As CMS pointed out, it's equivalent to: []['sort']['call']()["btoa"]("00")[1];

They build the strings by pulling them out of things like false, etc.

For example, to get the s in "sort":

Get a "false": (![]+[]) -- ![] returns false and +[] converts it to a string.

Get the value 3 with: !+[]+!+[]+!+[] - each !+[] returns true, but when you add booleans you get an integer representation. e.g. true + true = 2

Get the s with string index access notation ("false"[3] = 's'): (![]+[]) [!+[]+!+[]+!+[]]

And now you have an s. They keep doing that until they have enough to access whichever method or property they want.

CD Sanchez
+1 nice explanation. Thanks!
BrunoLM