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 -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/PGYB6ARHJMUAC4TY4X2HXU4ANZ33KIUN/ Code of Conduct: http://python.org/psf/codeofconduct/