Как безопасно выгрузить данные из 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 не будет опубликован. Обязательные поля помечены *