我有一个腌制的对象实例,必须接受来自不受信任来源的这些腌制实例。有一个内部状态(只是一个整数数组),我可以用来重新创建实例而不执行任何pickle对象的代码。因此,我的问题是,是否可以从pickle中仅提取一些数据对象而不从中执行任何代码。
答案 0 :(得分:1)
一个想法可能是将文件中的pickled对象作为字符串读取,然后使用pickletools.dis
查看其中的内容...只允许特定的命令列表('STOP
','{{ 1}}',...)在第二列。如果您只关注基本python对象的非常具体的列表,那么 可能会 能够安全地做到这一点。
以下是您使用INT
获得的信息:
pickletools.dis
这比编写一个完整的pickle解析器更好,如果你只想允许像>>> import pickletools
>>> import pickle
>>>
>>> p1 = pickle.dumps(1)
>>> p2 = pickle.dumps(min)
>>>
>>> pickletools.dis(p1)
0: I INT 1
3: . STOP
highest protocol among opcodes = 0
>>> pickletools.dis(p2)
0: c GLOBAL '__builtin__ min'
17: p PUT 0
20: . STOP
highest protocol among opcodes = 0
>>>
这样的简单对象,那可能是可行的。
答案 1 :(得分:0)
你可以这样做,但只有你自己解析数据,而不是依赖可能导致任意代码执行的pickle。一个非常简单的例子可能是
import pickle
import re
class Test(object):
def __init__(self, l):
self.internal_list = l
self.foo = 2
self.bar = 24
# Create a pickled version of an object
t = Test([1,2,3,4,5,6,7,8,9,10])
pickle.dump(t, open("test.pickle",'w'))
def find_last_integer(s):
""" Parses a string to return the integer that it ends with
e.g. find_last_integer("foobar312") == 312
"""
return int(re.search(r"\d+$", s).group())
# Load the pickled data
data = open("test.pickle").read()
listdata = data[data.find("(lp"):].split('\n') # Assumes that the class will only contain one list
# if you need more then look for all lines starting "(lp"
nelements = find_last_integer(listdata[0])
# Each element of the list should be of the form "In" or "aIn"
reconstructed = [find_last_integer(elem) for elem in listdata[1:nelements+1]]
print reconstructed
请注意,如果您将其与其他版本一起使用,我只在python 2.7.8 YMMV中测试了上述代码。