[pypy-commit] pypy default: Issue #2629
arigo
pypy.commits at gmail.com
Mon Aug 14 13:15:46 EDT 2017
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r92147:8775f1e1bf8b
Date: 2017-08-14 19:14 +0200
http://bitbucket.org/pypy/pypy/changeset/8775f1e1bf8b/
Log: Issue #2629
Uninitialized instances of 'property' or 'super' should not cause
segfaults
diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -28,12 +28,19 @@
objtype_name = "<%s object>" % self.w_objtype.getname(space)
else:
objtype_name = 'NULL'
+ if self.w_starttype is not None:
+ starttype_name = self.w_starttype.getname(space)
+ else:
+ starttype_name = 'NULL'
return space.newtext("<super: <class '%s'>, %s>" % (
- self.w_starttype.getname(space), objtype_name))
+ starttype_name, objtype_name))
def get(self, space, w_obj, w_type=None):
if self.w_self is not None or space.is_w(w_obj, space.w_None):
return self
+ if self.w_starttype is None:
+ raise oefmt(space.w_TypeError,
+ "__get__(x) is invalid on an uninitialized instance of 'super'")
else:
# if type(self) is W_Super:
# XXX write a fast path for this common case
@@ -45,6 +52,7 @@
# only use a special logic for bound super objects and not for
# getting the __class__ of the super object itself.
if self.w_objtype is not None and name != '__class__':
+ assert self.w_starttype is not None
w_value = space.lookup_in_type_starting_at(self.w_objtype,
self.w_starttype,
name)
@@ -114,7 +122,11 @@
_immutable_fields_ = ["w_fget", "w_fset", "w_fdel"]
def __init__(self, space):
- pass
+ self.w_fget = space.w_None
+ self.w_fset = space.w_None
+ self.w_fdel = space.w_None
+ self.w_doc = space.w_None
+ self.getter_doc = False
@unwrap_spec(w_fget=WrappedDefault(None),
w_fset=WrappedDefault(None),
diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -419,3 +419,35 @@
assert x.y == 42
del x.x
assert x.z == 42
+
+ def test_uninitialized_property(self):
+ p = property.__new__(property)
+ raises(AttributeError, p.__get__, 42)
+ raises(AttributeError, p.__set__, 42, None)
+ raises(AttributeError, p.__delete__, 42)
+ assert repr(p).startswith("<property object at ")
+ assert p.fget is p.fset is p.fdel is p.__doc__ is None
+ #
+ lst = []
+ p.deleter(lst.append).__delete__(42)
+ assert lst == [42]
+ #
+ lst = []
+ p.getter(lst.append).__get__(43)
+ assert lst == [43]
+ #
+ lst = []
+ p.setter(lambda x, y: lst.append((x, y))).__set__(44, 45)
+ assert lst == [(44, 45)]
+
+ def test_uninitialized_super(self):
+ s = super.__new__(super)
+ assert repr(s) == "<super: <class 'NULL'>, NULL>"
+ assert s.__thisclass__ is s.__self__ is s.__self_class__ is None
+ assert s.__get__(None, "anything") is s
+ raises(TypeError, s.__get__, 42)
+ raises(TypeError, s.__get__, int)
+ raises(TypeError, s.__get__, type(None))
+ raises(AttributeError, "s.abcde")
+ raises(AttributeError, "s.abcde = 42")
+ raises(AttributeError, "del s.abcde")
More information about the pypy-commit
mailing list