每个人都知道 pickle 不是一种安全的用户数据存储方式。它甚至在盒子上这样写。
我正在寻找在当前支持的 cPython >= 2.4
版本中破坏 pickle 解析的字符串或数据结构的示例。有没有可以 pickle 但不能不 pickle 的东西?特定的 unicode 字符有问题吗?真正的大数据结构?显然,旧的 ASCII 协议(protocol)存在一些问题,但最新的二进制形式呢?
我特别好奇 pickle loads
操作可能失败的方式,尤其是当给定一个由 pickle 本身生成的字符串时。是否存在 pickle 会继续解析 .
的情况?
有哪些边缘情况?
编辑:以下是我正在寻找的一些示例:
- 在 Python 2.4 中,您可以毫无错误地 pickle 一个数组,但不能 unpickle。 http://bugs.python.org/issue1281383
- 在使用
__setstate__
设置实例变量之前,您无法可靠地 pickle 从 dict 继承并调用__setitem__
的对象。在 pickle Cookie 对象时,这可能是一个问题。参见 http://bugs.python.org/issue964868和 http://bugs.python.org/issue826897 - Python 2.4(和 2.5?)将返回一个无穷大的 pickle 值(或接近它的值,如 1e100000),但加载时可能(取决于平台)失败。参见 http://bugs.python.org/issue880990和 http://bugs.python.org/issue445484
- 最后一项很有趣,因为它揭示了
STOP
标记实际上并没有停止解析的情况 - 当标记作为文字的一部分存在时,或者更一般地说,当前面没有换行符时.
最佳答案
这是一个大大简化的示例,说明了 pickle 不喜欢我的数据结构的地方。
import cPickle as pickle
class Member(object):
def __init__(self, key):
self.key = key
self.pool = None
def __hash__(self):
return self.key
class Pool(object):
def __init__(self):
self.members = set()
def add_member(self, member):
self.members.add(member)
member.pool = self
member = Member(1)
pool = Pool()
pool.add_member(member)
with open("test.pkl", "w") as f:
pickle.dump(member, f, pickle.HIGHEST_PROTOCOL)
with open("test.pkl", "r") as f:
x = pickle.load(f)
众所周知,Pickle 对于循环结构有点搞笑,但如果您将自定义哈希函数和集合/字典混入其中,事情就会变得非常棘手。
在这个特定的示例中,它部分解开成员,然后遇到池。所以它然后部分解开池并遇到成员集。因此它创建了集合并尝试将部分未 pickle 的成员添加到集合中。此时它在自定义哈希函数中终止,因为该成员仅部分未被 pickle 。我不敢想象如果哈希函数中有一个“if hasattr...”会发生什么。
$ python --version
Python 2.6.5
$ python test.py
Traceback (most recent call last):
File "test.py", line 25, in <module>
x = pickle.load(f)
File "test.py", line 8, in __hash__
return self.key
AttributeError: ("'Member' object has no attribute 'key'", <type 'set'>, ([<__main__.Member object at 0xb76cdaac>],))
关于Python pickle - 它是如何损坏的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4132132/