Unpickler.load_inst(), Unpickler.load_obj(), Unpickler.load_build():

Fixed problems when unpickling in restricted execution environments.
These methods try to assign to an instance's __class__ attribute, or
access the instances __dict__, which are prohibited in REE.  For the
first two methods, I re-implemented the old behavior when assignment
to value.__class__ fails.

For the load_build() I also re-implemented the old behavior when
inst.__dict__.update() fails but this means that unpickling in REE is
semantically different than unpickling in unrestricted mode.
This commit is contained in:
Barry Warsaw 1998-01-26 22:47:35 +00:00
parent 5da0f504ba
commit abe2a457de
1 changed files with 28 additions and 7 deletions

View File

@ -601,11 +601,17 @@ class Unpickler:
module = self.readline()[:-1] module = self.readline()[:-1]
name = self.readline()[:-1] name = self.readline()[:-1]
klass = self.find_class(module, name) klass = self.find_class(module, name)
instantiated = 0
if (not args and type(klass) is ClassType and if (not args and type(klass) is ClassType and
not hasattr(klass, "__getinitargs__")): not hasattr(klass, "__getinitargs__")):
value = _EmptyClass() try:
value.__class__ = klass value = _EmptyClass()
else: value.__class__ = klass
except RuntimeError:
# In restricted execution, assignment to inst.__class__ is
# prohibited
pass
if not instantiated:
value = apply(klass, args) value = apply(klass, args)
self.append(value) self.append(value)
dispatch[INST] = load_inst dispatch[INST] = load_inst
@ -617,11 +623,18 @@ class Unpickler:
del stack[k + 1] del stack[k + 1]
args = tuple(stack[k + 1:]) args = tuple(stack[k + 1:])
del stack[k:] del stack[k:]
instantiated = 0
if (not args and type(klass) is ClassType and if (not args and type(klass) is ClassType and
not hasattr(klass, "__getinitargs__")): not hasattr(klass, "__getinitargs__")):
value = _EmptyClass() try:
value.__class__ = klass value = _EmptyClass()
else: value.__class__ = klass
instantiated = 1
except RuntimeError:
# In restricted execution, assignment to inst.__class__ is
# prohibited
pass
if not instantiated:
value = apply(klass, args) value = apply(klass, args)
self.append(value) self.append(value)
dispatch[OBJ] = load_obj dispatch[OBJ] = load_obj
@ -756,7 +769,15 @@ class Unpickler:
try: try:
setstate = inst.__setstate__ setstate = inst.__setstate__
except AttributeError: except AttributeError:
inst.__dict__.update(value) try:
inst.__dict__.update(value)
except RuntimeError:
# XXX In restricted execution, the instance's __dict__ is not
# accessible. Use the old way of unpickling the instance
# variables. This is a semantic different when unpickling in
# restricted vs. unrestricted modes.
for k, v in value.items():
setattr(inst, k, v)
else: else:
setstate(value) setstate(value)
dispatch[BUILD] = load_build dispatch[BUILD] = load_build