Я интересуюсь пониманием внутренностей JavaScript. Я попытался считать источник для SpiderMonkey и Носорога, но это довольно сложно для переноса моей головы.
Причина, которую я спрашиваю: почему чему-то нравится
(![]+[])[+!![]+[]]
произвести "a"
(Å=[],[µ=!Å+Å][µ[È=++Å+Å+Å]+({}+Å)[Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])()[µ[Å]+µ[Å+Å]+Ç[È]+ª](Å)
произвести alert(1)
?Источник: http://sla.ckers.org/forum/read.php?24,32930,page=1.
Существует намного больше примеров причуд JavaScript на том форуме, и я хотел знать, как он работает с точки зрения программирования относительно безопасности веб-приложения.
Почему (! [] + []) [+ !! [] + []]
создать "a"
шаг за шагом: это разбирается в: (! [] + [])
и [+ !! [] + []]
. Первый бит уже объяснялся artemb: []
- это массив. В противном случае ! []
оценивается как логическое, false
- вот как !
работает, когда он применяется к чему-то, что не null
или не определено. Опять же, как указал artemb, добавление этого + []
заставляет логическое значение быть преобразовано в строку. Это потому, что +
- это оператор конкатенации строк. Логическое значение false
затем преобразуется в его строковое представление «false»
.
Затем второй бит, [+ !! [] + []]
. Прежде всего, внешние [
и ]
служат для обработки предыдущей строки, которая, как мы только что получили, равна «false»
как массив символов.Помещая целочисленный индекс внутри [
и ]
, вы получаете символ по определенному индексу. Остается + !! [] + []
Он состоит из 4 частей: +
, !! []
, +
и []
. Сначала оценивается !! []
. Мы уже видели, что ! []
является логическим false
, поэтому добавляется еще один !
отрицает это и дает истину
. Следующее, что происходит, - применяется +
в + !! []
, и, применяя +
, он преобразует логическое в истинное
в числовое представление, которое является 1
(так + true
равно 1
). + []
, которое следует за что 1
дает «1»
, но на самом деле это не имеет смысла, более короткое выражение (! [] + []) [+ !! []]
уже производит a
. Добавление + []
тоже не повредит, результирующее выражение будет просто ["1"]
вместо [1]
. Я догадываюсь, что когда []
применяется к массиву, все, что находится внутри []
, будет преобразовано в число, которое для «1»
снова даст 1
.Так или иначе, + !! [] + []
оценивается как 1
, что делает окончательное выражение: "false" [1]
, которое говорит: дай мне символ с индексом 1 из строки «false»
, и поскольку по умолчанию массивы начинаются с 0
в javascript, это второй символ «false»
и a
.
Почему (! [] + []) [+! [] + []) [+ !! [] + []] производят "A"
! EXPR
- называет Toboolean на EXPR и переворачивает логическое значение. Другими словами, правдивые значения, такие как пустой массив, будут производить ложь при использовании с не оператором. A + B
- Оба выражения проходят через внутреннюю веруми. Если либо результирующее значение является строкой, выполняется конконтрация строки. В противном случае примитивы проходят через тонубил и добавлены. Toprimitive для объектов (включенные массивы) попробуют ToString и ValueOf. Array.Prototype.toString действует как призыв к присоединению без параметров. Таким образом, ! [] + [] = False + "" = "false"
!! [] == true
, Оператор unary Plus преобразует выражение в число, поэтому
. Опять же, массив преобразуется в «
так + !! [] + [] ==« 1 »
. («false») [«1»] == «A»
Другое выражение может быть отварно в аналогичной форме. Он использует строки Unicode, чтобы испортить его, и он дольше, но так же, как прямой на «анализ».
Я рекомендую вам получить и прочитать:
Если вы хотите понять, почему эти странные выражения работают, как они это делают, вы можете открыть консоль Firebug и экспериментировать сами. Я сделал, и я получил это ! []
[] [] []
false
, !! []
IS true
, добавляя массив на логическое значение ( FALSE + []
или TRUE + []
) создает строку-версию этого значения ( false + [] = "false"
).
Таким образом, выражение сводится к:
"false"["1"]
, который, очевидно, «A»