2010-01-20 24 views
11

Estoy interesado en comprender las partes internas de JavaScript. Intenté leer la fuente de SpiderMonkey y Rhino, pero es bastante complejo entenderlo.¿Por qué (! [] + []) [+ !! [] + []] produce "a"

La razón por la que pregunto es: ¿por qué algo así como

  • (![]+[])[+!![]+[]] productos "a"
  • (Å=[],[µ=!Å+Å][µ[È=++Å+Å+Å]+({}+Å)[Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])()[µ[Å]+µ[Å+Å]+Ç[È]+ª](Å) producen alert(1)?

Fuente: http://sla.ckers.org/forum/read.php?24,32930,page=1.

Hay muchos más ejemplos de rarezas de JavaScript en ese foro y quería saber cómo funciona desde el punto de vista de la programación con respecto a la seguridad de las aplicaciones web.

+0

si está interesado en cómo funcionan los idiomas, nada mejor que escribir un compilador para usted mismo, que básicamente le enseñará el idioma y sus aspectos internos. – Chii

+0

Gracias por todas las respuestas. Sabía que Javascript era mágico, pero algunas de las cosas que hace es peligroso ... – prafulfillment

Respuesta

12

¿Por qué (![]+[])[+!![]+[]] productos "a"

paso a paso: esto se analiza en: (![]+[]) y [+!![]+[]]. El primer bit ya fue explicado por artemb: [] es una matriz. Negándolo, ![] evalúa a un booleano, false - así es como funciona ! cuando se aplica a algo que no es null o indefinido. De nuevo, como lo señala artemb, al anexar este +[] se fuerza que el booleano se convierta en una cadena. Eso es porque el + es un operador de concatenación de cadenas. El booleano false se convierte a su representación de cadena, "false".

Luego, el segundo bit, [+!![]+[]]. En primer lugar, el [ externo y el ] sirven para tratar la cadena anterior, que acabamos de derivar es igual a "false" como una matriz de caracteres. Al poner un índice entero dentro de [ y ], obtiene el carácter en un índice en particular. Entonces lo que queda es +!![]+[] Esto consta de 4 piezas: +, !![], + y []. Primero se evalúa !![].Ya vimos que ![] es un booleano false por lo que anteponer otro ! lo niega, y produce true. Lo siguiente que lo que sucede es que el + en +!![] consigue aplicada, y mediante la aplicación de + que convierte el booleano true en la representación de los números, que es 1 (por lo +true es 1) El +[] que sigue hace una cadena de nuevo desde que 1 rendimiento "1" pero realmente no tiene sentido, la expresión más corta (![]+[])[+!![]] ya produce a. Agregar +[] tampoco hace daño, la expresión resultante es simplemente ["1"] en lugar de [1]. Mi corazonada es que cuando se aplica [] a una matriz, lo que esté dentro de [] se forzará en un número, que para "1" daría 1 nuevamente. Entonces, de cualquier manera, +!![]+[] evalúa a 1, haciendo la expresión final: "false"[1] que está diciendo: dame el carácter en el índice 1 de la cadena "false", y como por defecto las matrices comienzan en 0 en javascript, este es el segundo caracter de "false", y a.

16

Si quiere entender por qué esas expresiones extrañas funcionan como lo hacen, puede abrir la consola de Firebug y experimentar usted mismo. Lo hice y obtuve que ![] es false, !![] es true, agregando una matriz a un valor booleano (false+[] o true+[]) produce una versión de cadena de este valor (false+[]="false").

De esta manera la expresión se reduce a:

"false"["1"] 

que es obviamente "a"

+4

¿Cómo es eso obvio? – medopal

+0

Es obvio en el sentido de que, si tiene suficiente tiempo en sus manos y un poco de creatividad, puede usar este conjunto limitado de concatenación de cadenas y accesadores de índices para crear cadenas arbitrarias. –

+0

@medopal Quizás no del todo obvio :) Es el índice de la letra "a" en la cadena "falso" ('f' = 0, 'a' = 1, 'l' = 2, 's' = 3 , 'e' = 4). –

1

recomiendo que obtener y leer:

  • estándar ECMAScript (ECMA 262), quinto edición
  • Documento de Adobe denominado "Visión general de AVM 2" que explica la arquitectura de la máquina virtual AVM2, en la cual Adobe Flash y su ActionScript correr.
2

¿Por qué [+ !! [] + []] producen "a"

  1. !expr ([] + []!) - Llamadas ToBoolean en expr y voltea el valor booleano. En otras palabras, los valores verdaderos como una matriz vacía producirán falso cuando se usan con el operador no.
  2. a + b - Ambas expresiones se ejecutan a través de ToPrimitive interno. Si el valor resultante es una cadena, se realiza la concatenación de cadenas. De lo contrario, las primitivas se ejecutan en ToNumber y se agregan. ToPrimitive para objetos (matrices incluidas) intentará toString y valueOf. Array.prototype.toString actúa como combinación de llamada sin parámetros. Por lo tanto, ![] + [] = false + "" = "false"
  3. !![] == true, el operador unario convierte la expresión en un número, entonces 1. De nuevo, la matriz se convierte en "" para +!![]+[] == "1".
  4. La expresión se reduce a ("false")["1"] == "a"

la otra expresión se puede reducir de una manera similar. Utiliza cadenas unicode para estropearlo y es más largo, pero igual de sencillo de "analizar".

Cuestiones relacionadas