On Wed, Jul 15, 2020, at 07:40, Steven D'Aprano wrote:
> On Tue, Jul 14, 2020 at 09:47:15PM -0400, Random832 wrote:
>
> > I was asking for the current Unpickler class, which currently has a
> > whitelist hook for loading globals, to be modified to also have a
> > whitelist hook so that an application can provide a function that
> > looks at a callable and its arguments that the pickle proposes to
> > call, and can choose to either evaluate it, raise an error, or return
> > a substitute value.
>
> Could you provide a proof of concept subclass?
I was thinking of something like this... this is largely a trivial modification
of the pure-python unpickler, but there's no methods that can be overridden for
this effect in the C one.
class MyUnpickler(pickle._Unpickler):
# this method is intended to be overriden by subclasses
def do_call(self, func, *a, **k):
#print(f"blocked call {func}(*{a}, **{k})")
#return None
raise NotImplementedError("This unpickler can't handle this pickle")
# these methods are defined the same as in _Unpickler except for the use of
do_call
def _instantiate(self, klass, args):
if (args or not isinstance(klass, type) or
hasattr(klass, "__getinitargs__")):
try:
value = do_call(klass, *args)
except TypeError as err:
raise TypeError("in constructor for %s: %s" %
(klass.__name__, str(err)), sys.exc_info()[2])
else:
value = do_call(klass.__new__, klass)
self.append(value)
def load_newobj(self):
args = self.stack.pop()
cls = self.stack.pop()
obj = self.do_call(cls.__new__, cls, *args)
self.append(obj)
def load_newobj_ex(self):
kwargs = self.stack.pop()
args = self.stack.pop()
cls = self.stack.pop()
obj = self.do_call(cls.__new__, cls, *args, **kwargs)
self.append(obj)
def load_reduce(self):
stack = self.stack
args = stack.pop()
func = stack[-1]
stack[-1] = self.do_call(func, *args)
dispatch = pickle._Unpickler.dispatch.copy()
# load_inst and load_obj use _instantiate and don't need to be overridden
directly
dispatch[pickle.NEWOBJ[0]] = load_newobj
dispatch[pickle.NEWOBJ_EX[0]] = load_newobj_ex
dispatch[pickle.REDUCE[0]] = load_reduce
def loads(s, /, *, fix_imports=True, encoding="ASCII", errors="strict",
buffers=None, unpickler=pickle.Unpickler):
if isinstance(s, str):
raise TypeError("Can't load pickle from unicode string")
file = io.BytesIO(s)
return unpickler(file, fix_imports=fix_imports, buffers=buffers,
encoding=encoding, errors=errors).load()
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/PGYB6ARHJMUAC4TY4X2HXU4ANZ33KIUN/
Code of Conduct: http://python.org/psf/codeofconduct/