Как безопасно выгрузить данные из pickle-файла, модифицировать их, и обратно сдампить в Pickle?



@Derfirm

Здравствуй, добрый человек!

Мне необходимо реализовать такой каприз. В обработку поступает пикл-файл (преимущественно 2 прото-версии, но это не принципиально), в котором имеются как и встроенные типы/структуры данных (словари, множества и так далее) так и классы/модули из пользовательского пространства. Мне необходимо загрузить содержимое файла (при этом не доставлять/не импортировать или самостоятельно не описывать пользовательские классы или модули). В дальнейшем я предполагаю какую-то модификацию встроенных типов (например добавили значение в словарь из этого дампа или поменяли значение в другом словаре) и модицифированное содержимое обратно поместить в пикл, не повредив его при этом).

Если попробовать схематически расписать флоу, то оно выглядит примерно так:
– загружаем модуль (попутно фейками неимпортируемые объекты)
– модифицируем загруженные объекты
– дампим обратно весь модуль с модифицированными объектами

Вопрос включает несколько других вопросов.
– Какой предпочтительный путь распознавания неимпортируемых объектов (пользовательские импорты или объекты) и чем их заменять.
– Каким подходом воспользоваться для удобной модификации объектов из распикленного содержимого (условно – как хранить то что мы загрузим при дессериализации пикла)
– Как первые два пункта сделать настолько аккуратно, чтобы потом смочь запаковать контент (сдампить) обратно в такой же пикл, но с примесью уже модифицированного нами контента?
– Как сериализовать пикл и случайно не выполнить вредоносные инструкции?

UPD: с такой историей могли столкнуться, к примеру, те кто работает с `renpy` и декодирует файлы игры и файлы сохранений.

UPD_1: Работаю в большой существующей экосистеме и моей целью не стоит “выдумать новый формат”. Увы, его уже выдумали (пиклить содержимое и таким образом сохранять состояние процесса) и моей задачей стоит работать с ним.

UPD_2: Авторы экосистемы ака фреймворком вообще никак не связаны со мной и с моим заказчиком, их философия плюс-минус заключается в “дамп не покидает рабочую станцию”. Есть другие люди, те, кто пользуется этим фреймворком для написание софта и они пиклят свое состояние (тут уже появляются и дампятся их собственные сущности). С этими людьми у меня нет возможности контактировать и тем более настроить некий обмен версиями.
Зато есть те, кто пользуется софтом и вот уже их проблемы мне нужно решать (они тоже по факту готовы делиться лишь дампом, но никак не купленым софтом)


Решения вопроса 0


Ответы на вопрос 1



@Assargin

Давайте начнём с того, что откроем для себя, как пикл сериализует классы:

>>> class MyKnowHowClass:
...   SECRET = '42'
...   TOP_SECRET = 'Kennedi was killed by UFO'
... 
>>> import pickle
>>> pickle.dumps(MyKnowHowClass)
'c__main__nMyKnowHowClassnp0n.'
>>>

То есть, это всего лишь “указатель”, описание того, откуда брать структуру данных. Если пикл не найдёт класс там, где указано – будет ЕГГОГ.
Встроенные типы – ок. Наполняйте встроенные типы (списки, сеты, словари и т.п.) такими же встроенными типами (то же самое + скаляры) – и будет вам автономный пикл.
А с пользовательскими классами – не-а.

UPD:
Если у вас экосистема, и тем более большая, и тем более уже выдумали “формат” – наверняка уже должны быть решены многие вопросы. Например, вопросы безопасности (ваш п.4), вопросы о загрузке-выгрузке (п.3), да и много чего можно посмотреть существующего и работающего на тему лучших практик по остальным двум пунктам.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *