Yet another way to invoke functions without parentheses
Найден ещё один способ вызова произвольных функций в JavaScript без круглых скобок. Он основан на переопределении функции prepareStackTrace объекта Error, которая обычно форматирует трассировку стека и вызывается при обращении к свойству stack ошибки. Эта функция получает два аргумента — саму ошибку и структурированное представление стека в виде массива позиций кода. Ключевой момент: её сигнатура совпадает с сигнатурой конструктора Function, который генерирует функции, если второй аргумент — валидный код JavaScript.
Однако массив позиций кода не является валидным кодом, поэтому при попытке вызова возникает синтаксическая ошибка. Чтобы обойти это, нужно управлять результатом Array.prototype.toString(), возвращая нужный код. Автор предлагает два пути: переопределить метод константной функцией или использовать загрязнение прототипа, внедрив полезную нагрузку через Object.prototype.message и заменив Array.prototype.toString на Error.prototype.toString.
Собрав всё вместе, можно сгенерировать произвольную функцию. Остаётся её вызвать — например, через трюк с valueOf, переопределив его и приведя объект к примитиву, либо через toString с конкатенацией строки. Итоговая нагрузка: Object.prototype.message='alert\x281337\x29';Array.prototype.toString=Error.prototype.toString;Error.prepareStackTrace = Function;const x = new Error;x.valueOf=x.stack;+x; — её можно проверить прямо в консоли браузера.