JavaScript, длина строки 1, 960 956 928 байт
[
t
,
r
,
u
,
e
,
f
,
a
,
l
,
s
]
=
!
0
+
[
!
1
]
;
[
,
n
,
d
,
,
q
,
i
]
=
t
.
a
+
t
V
=
[
]
[
f
+
i
+
n
+
d
]
;
[
,
,
,
c
,
,
,
o
,
,
_
,
,
,
,
,
y
,
z
]
=
V
+
0
F
=
V
[
E
=
c
+
o
+
n
+
s
+
t
+
r
+
u
+
c
+
t
+
o
+
r
]
P
=
(
1
+
e
+
2
+
3
-
4
+
t
)
[
2
]
f
=
F
(
r
+
e
+
t
+
u
+
r
+
n
+
_
+
a
+
t
+
o
+
(
0
+
{
}
)
[
3
]
)
(
)
(
3
*
4
+
[
]
[
E
]
[
n
+
a
+
(
0
[
E
]
+
0
)
[
9
+
2
]
+
e
]
)
[
1
]
F
(
a
,
a
+
l
+
e
+
r
+
t
+
y
+
a
+
P
+
q
+
P
+
a
+
P
+
q
+
z
)
`
[
t
,
r
,
u
,
e
,
f
,
a
,
l
,
s
]
=
!
0
+
[
!
1
]
;
[
,
n
,
d
,
,
q
,
i
]
=
t
.
a
+
t
V
=
[
]
[
f
+
i
+
n
+
d
]
;
[
,
,
,
c
,
,
,
o
,
,
_
,
,
,
,
,
y
,
z
]
=
V
+
0
F
=
V
[
E
=
c
+
o
+
n
+
s
+
t
+
r
+
u
+
c
+
t
+
o
+
r
]
P
=
(
1
+
e
+
2
+
3
-
4
+
t
)
[
2
]
f
=
F
(
r
+
e
+
t
+
u
+
r
+
n
+
_
+
a
+
t
+
o
+
(
0
+
{
}
)
[
3
]
)
(
)
(
3
*
4
+
[
]
[
E
]
[
n
+
a
+
(
0
[
E
]
+
0
)
[
9
+
2
]
+
e
]
)
[
1
]
F
(
a
,
a
+
l
+
e
+
r
+
t
+
y
+
a
+
P
+
q
+
P
+
a
+
P
+
q
+
z
)
`
Более удобочитаемая версия, которая также называется quine (посторонние переводы строки удалены):
[t,r,u,e,f,a,l,s]=!0+[!1];[,n,d,,q,i]=t.a+t
V=[][f+i+n+d];[,,,c,,,o,,_,,,,,y,z]=V+0
F=V[E=c+o+n+s+t+r+u+c+t+o+r]
P=(1+e+2+3-4+t)[2]
f=F(r+e+t+u+r+n+_+a+t+o+(0+{})[3])()(3*4+[][E][n+a+(0[E]+0)[9+2]+e])[1]
F(a,a+l+e+r+t+y+a+P+q+P+a+P+q+z)`
[t,r,u,e,f,a,l,s]=!0+[!1];[,n,d,,q,i]=t.a+t
V=[][f+i+n+d];[,,,c,,,o,,_,,,,,y,z]=V+0
F=V[E=c+o+n+s+t+r+u+c+t+o+r]
P=(1+e+2+3-4+t)[2]
f=F(r+e+t+u+r+n+_+a+t+o+(0+{})[3])()(3*4+[][E][n+a+(0[E]+0)[9+2]+e])[1]
F(a,a+l+e+r+t+y+a+P+q+P+a+P+q+z)`
объяснение
Уф. Приезжайте сюда, потому что это будет коварное путешествие ...
Я потратил много времени, пытаясь понять, как решить эту проблему с длиной 1 - без встроенных (напрямую, во всяком случае), ключевых слов или даже функций стрелок - прежде чем понять, что это легко возможно с помощью JSF *** , который может оценивать любой код JavaScript, избегая при этом многобайтовых токенов. Но решение JSF легко может быть длиной в тысячи байтов, если не десятками или сотнями тысяч. К счастью, мы не ограничены только - у ()[]+!
нас есть все ASCII в нашем распоряжении!
Я решил начать с игры в гольф с основных строительных блоков JSF - персонажей, которые можно объединить в строки, чтобы, так сказать, «открыть больше функций». Мы не можем напрямую использовать строки для получения символов, так как для этого потребуются строки длиной 3. Поэтому вместо этого мы крадем уловку из JSF, получая несколько символов из литералов, которые могут быть созданы с помощью однобайтовых токенов:
JSF*** Used here Value Chars unlocked
!![] !0 true true
![] !1 false fals
[][[]] t.a undefined ndi
Из них мы можем расширяться наружу, начиная с того [].find
, что является объектом Function. Преобразование этого в строку function find() { ...
дает нам доступ к c
, o
пространство ( _
), а также круглые скобки ( y
и z
). Возможно , что еще более важно, мы теперь имеем доступ к его constructor
, в Function
функции-которой, inceptional , как это может показаться, дает нам возможность выполнения кода путем создания строки, передавая ее Function()
, а затем вызвать функцию генерируемый.
Вероятно, я должен упомянуть общий метод, используемый самой программой. Начиная с 2015 года, в JavaScript появилась эта действительно классная функция, называемая « теговыми шаблонами », которая не только позволяет неэкранированные символы новой строки в строках, но и позволяет напрямую вызывать функцию со строковым литералом (в некотором смысле; myFunc`abc`;
примерно эквивалентно myFunc(["abc"])
). Если мы поместим вызов функции как последнюю вещь в программе, общая структура будет выглядеть так:
code;func`code;func`
Все, func
что нужно сделать, - это вывести свой аргумент, после которого следует символ обратной черты, затем снова его аргумент и второй знак обратной черты. Предполагая, что у нас есть аргумент a
и обратный трюк f
, мы можем сделать это с помощью кода alert(a+f+a+f)
. Однако на данный момент нам не хватает +
и самого обратного удара. +
(хранится в P
) не сложно; мы украли еще один трюк у JSF, построив строку 1e23
, преобразовав ее в число, а затем вернув обратно в строку, и дали "1e+23"
.
Получение обратного удара немного сложнее. Сначала я попытался получить String.fromCharCode
, но найти C
оказалось почти так же сложно. К счастью, atob
его достаточно просто получить ( Function("return atob")()
; b
генерируется из 0+{}
, который дает [object Object]
) и может дать любой символ ASCII, если найдена правильная магическая строка. Короткий скрипт дал мне 12A
один из вариантов, который удобно найти в 12Array
(немного короче, благодаря [].constructor[n+a+m+e]
; m
находится в 0 .constructor+0
:) "function Number() { ..."
.
Наконец, мы склеиваем все вместе. Мы назначаем обратную переменную переменной f
, но поскольку мы не можем использовать ее непосредственно в строке функции, мы вместо этого устанавливаем переменную q
на букву f
и используем ее вместо этого. Это делает нашу последнюю строку a+l+e+r+t+y+a+P+q+P+a+P+q+z
или "alert(a+f+a+f)"
. Затем Function()
мы передаем это, передаем наш готовый код в результат, и вуаля, у нас есть JavaScript-квин с не более чем одним символом на строку!
В данный момент моя голова чувствует себя ужасно, поэтому, пожалуйста, узнайте обо всех моих ошибках или вещах, которые я пропустил в этом объяснении, и я вернусь к вам после того, как немного отдохну ...