mirror of https://github.com/python/cpython
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:
parent
5da0f504ba
commit
abe2a457de
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue