Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r95019:0ba874a49cee
Date: 2018-08-22 08:46 +0200
http://bitbucket.org/pypy/pypy/changeset/0ba874a49cee/
Log: Issue #2874
Add a runtime check that we don't overwrite 'def buffer_w()' without
also setting the '__buffer' flag in the TypeDef. Fix various places
where it was missing.
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1510,10 +1510,19 @@
if readonly and flags & self.BUF_WRITABLE == self.BUF_WRITABLE:
raise oefmt(self.w_BufferError, "Object is not writable.")
+ def _try_buffer_w(self, w_obj, flags):
+ if not we_are_translated():
+ if w_obj.buffer_w.im_func != W_Root.buffer_w.im_func:
+ # when 'buffer_w()' is overridden in the subclass of
+ # W_Root, we need to specify __buffer="read" or
+ # __buffer="read-write" in the TypeDef.
+ assert type(w_obj).typedef.buffer is not None
+ return w_obj.buffer_w(self, flags)
+
def buffer_w(self, w_obj, flags):
# New buffer interface, returns a buffer based on flags
(PyObject_GetBuffer)
try:
- return w_obj.buffer_w(self, flags)
+ return self._try_buffer_w(w_obj, flags)
except BufferInterfaceNotFound:
raise oefmt(self.w_TypeError,
"'%T' does not support the buffer interface", w_obj)
@@ -1521,14 +1530,14 @@
def readbuf_w(self, w_obj):
# Old buffer interface, returns a readonly buffer
(PyObject_AsReadBuffer)
try:
- return w_obj.buffer_w(self, self.BUF_SIMPLE).as_readbuf()
+ return self._try_buffer_w(w_obj, self.BUF_SIMPLE).as_readbuf()
except BufferInterfaceNotFound:
self._getarg_error("bytes-like object", w_obj)
def writebuf_w(self, w_obj):
# Old buffer interface, returns a writeable buffer
(PyObject_AsWriteBuffer)
try:
- return w_obj.buffer_w(self, self.BUF_WRITABLE).as_writebuf()
+ return self._try_buffer_w(w_obj, self.BUF_WRITABLE).as_writebuf()
except (BufferInterfaceNotFound, OperationError):
self._getarg_error("read-write bytes-like object", w_obj)
@@ -1562,7 +1571,7 @@
# NB. CPython forbids surrogates here
return StringBuffer(w_obj.text_w(self))
try:
- return w_obj.buffer_w(self, self.BUF_SIMPLE).as_readbuf()
+ return self._try_buffer_w(w_obj, self.BUF_SIMPLE).as_readbuf()
except BufferInterfaceNotFound:
self._getarg_error("bytes or buffer", w_obj)
elif code == 's#':
@@ -1574,7 +1583,7 @@
if self.isinstance_w(w_obj, self.w_unicode): # NB. CPython forbids
return w_obj.text_w(self) # surrogates here
try:
- return w_obj.buffer_w(self, self.BUF_SIMPLE).as_str()
+ return self._try_buffer_w(w_obj, self.BUF_SIMPLE).as_str()
except BufferInterfaceNotFound:
self._getarg_error("bytes or read-only buffer", w_obj)
elif code == 'w*':
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -28,6 +28,9 @@
self.bases = bases
# Used in cpyext to fill tp_as_buffer slots
assert __buffer in {None, 'read-write', 'read'}, "Unknown value for
__buffer"
+ for base in bases:
+ if __buffer is None:
+ __buffer = base.buffer
self.buffer = __buffer
self.heaptype = False
self.hasdict = '__dict__' in rawdict
diff --git a/pypy/module/_cffi_backend/cbuffer.py
b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -156,7 +156,7 @@
return MiniBuffer(LLBuffer(ptr, size), w_cdata)
MiniBuffer.typedef = TypeDef(
- "_cffi_backend.buffer",
+ "_cffi_backend.buffer", None, None, "read-write",
__new__ = interp2app(MiniBuffer___new__),
__len__ = interp2app(MiniBuffer.descr_len),
__getitem__ = interp2app(MiniBuffer.descr_getitem),
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -191,7 +191,7 @@
W_ArrayInstance.typedef = TypeDef(
- 'ArrayInstance',
+ 'ArrayInstance', None, None, "read-write",
__repr__ = interp2app(W_ArrayInstance.descr_repr),
__setitem__ = interp2app(W_ArrayInstance.descr_setitem),
__getitem__ = interp2app(W_ArrayInstance.descr_getitem),
@@ -215,7 +215,7 @@
self._free()
W_ArrayInstanceAutoFree.typedef = TypeDef(
- 'ArrayInstanceAutoFree',
+ 'ArrayInstanceAutoFree', None, None, "read-write",
__repr__ = interp2app(W_ArrayInstance.descr_repr),
__setitem__ = interp2app(W_ArrayInstance.descr_setitem),
__getitem__ = interp2app(W_ArrayInstance.descr_getitem),
diff --git a/pypy/module/_rawffi/callback.py b/pypy/module/_rawffi/callback.py
--- a/pypy/module/_rawffi/callback.py
+++ b/pypy/module/_rawffi/callback.py
@@ -135,7 +135,7 @@
return W_CallbackPtr(space, w_callable, w_args, w_result, flags)
W_CallbackPtr.typedef = TypeDef(
- 'CallbackPtr',
+ 'CallbackPtr', None, None, "read",
__new__ = interp2app(descr_new_callbackptr),
byptr = interp2app(W_CallbackPtr.byptr),
buffer = GetSetProperty(W_CallbackPtr.getbuffer),
diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -379,7 +379,7 @@
W_StructureInstance.typedef = TypeDef(
- 'StructureInstance',
+ 'StructureInstance', None, None, "read-write",
__repr__ = interp2app(W_StructureInstance.descr_repr),
__getattr__ = interp2app(W_StructureInstance.getattr),
__setattr__ = interp2app(W_StructureInstance.setattr),
@@ -401,7 +401,7 @@
self._free()
W_StructureInstanceAutoFree.typedef = TypeDef(
- 'StructureInstanceAutoFree',
+ 'StructureInstanceAutoFree', None, None, "read-write",
__repr__ = interp2app(W_StructureInstance.descr_repr),
__getattr__ = interp2app(W_StructureInstance.getattr),
__setattr__ = interp2app(W_StructureInstance.setattr),
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -654,7 +654,7 @@
def descr__getattr__(self, space, w_key):
return space.getattr(self.w_obj, w_key)
-W_GenericBox.typedef = TypeDef("numpy.generic",
+W_GenericBox.typedef = TypeDef("numpy.generic", None, None, "read-write",
__new__ = interp2app(W_GenericBox.descr__new__.im_func),
__getitem__ = interp2app(W_GenericBox.descr_getitem),
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -368,6 +368,9 @@
def warn(self, w_msg, w_warningcls, stacklevel=2):
pass
+ def _try_buffer_w(self, w_obj, flags):
+ return w_obj.buffer_w(self, flags)
+
# ----------
def translates(self, func=None, argtypes=None, seeobj_w=[], **kwds):
diff --git a/pypy/objspace/std/test/test_memoryobject.py
b/pypy/objspace/std/test/test_memoryobject.py
--- a/pypy/objspace/std/test/test_memoryobject.py
+++ b/pypy/objspace/std/test/test_memoryobject.py
@@ -376,7 +376,7 @@
return MockBuffer(space, self.w_list, self.w_dim, self.w_fmt, \
self.w_size, self.w_strides, self.w_shape)
-W_MockArray.typedef = TypeDef("MockArray",
+W_MockArray.typedef = TypeDef("MockArray", None, None, "read-write",
__new__ = interp2app(W_MockArray.descr_new),
)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit