Author: Brian Kearns <bdkea...@gmail.com> Branch: refactor-buffer-api Changeset: r70911:ac02d8345ef9 Date: 2014-04-23 21:06 -0400 http://bitbucket.org/pypy/pypy/changeset/ac02d8345ef9/
Log: fix validation of buffer writability diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -5,7 +5,7 @@ from rpython.rlib import jit, types from rpython.rlib.debug import make_sure_not_resized from rpython.rlib.objectmodel import (we_are_translated, newlist_hint, - compute_unique_id) + compute_unique_id, specialize) from rpython.rlib.signature import signature from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \ INT_MIN, INT_MAX, UINT_MAX @@ -1369,6 +1369,11 @@ BUF_FULL_RO = 1 BUF_CONTIG = 2 BUF_CONTIG_RO = 3 + BUF_WRITABLE = 4 + + def check_buf_flags(self, flags, readonly): + if flags & self.BUF_WRITABLE == self.BUF_WRITABLE and readonly: + raise oefmt(self.w_BufferError, "Object is not writable.") def buffer_w(self, w_obj, flags): # New buffer interface, returns a buffer based on flags (PyObject_GetBuffer) @@ -1402,6 +1407,26 @@ raise oefmt(self.w_TypeError, "expected a character buffer object") + def _getarg_error(self, expected, w_obj): + raise oefmt(self.w_TypeError, "must be %s, not %T", expected, w_obj) + + @specialize.arg(1) + def getarg_w(self, code, w_obj): + if code == 'w*': + try: + try: + return w_obj.buffer_w(self, self.BUF_WRITABLE) + except OperationError: + self._getarg_error("read-write buffer", w_obj) + except TypeError: + pass + try: + return w_obj.writebuf_w(self) + except TypeError: + self._getarg_error("read-write buffer", w_obj) + else: + assert False + # XXX rename these/replace with code more like CPython getargs for buffers def bufferstr_w(self, w_obj): # Directly returns an interp-level str. Note that if w_obj is a diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py --- a/pypy/module/_io/interp_bufferedio.py +++ b/pypy/module/_io/interp_bufferedio.py @@ -80,7 +80,7 @@ self._unsupportedoperation(space, "detach") def readinto_w(self, space, w_buffer): - rwbuffer = space.buffer_w(w_buffer, space.BUF_CONTIG) + rwbuffer = space.getarg_w('w*', w_buffer) length = rwbuffer.getlength() w_data = space.call_method(self, "read", space.wrap(length)) diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -41,7 +41,7 @@ def readinto_w(self, space, w_buffer): self._check_closed(space) - rwbuffer = space.buffer_w(w_buffer, space.BUF_CONTIG) + rwbuffer = space.getarg_w('w*', w_buffer) size = rwbuffer.getlength() output = self.read(size) diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -366,7 +366,7 @@ def readinto_w(self, space, w_buffer): self._check_closed(space) self._check_readable(space) - rwbuffer = space.buffer_w(w_buffer, space.BUF_CONTIG) + rwbuffer = space.getarg_w('w*', w_buffer) length = rwbuffer.getlength() try: buf = os.read(self.fd, length) diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py --- a/pypy/module/_io/test/test_bufferedio.py +++ b/pypy/module/_io/test/test_bufferedio.py @@ -139,6 +139,8 @@ raw = _io.FileIO(self.tmpfile) f = _io.BufferedReader(raw) assert f.readinto(a) == 5 + exc = raises(TypeError, f.readinto, memoryview(b"hello")) + assert str(exc.value) == "must be read-write buffer, not memoryview" f.close() assert a == 'a\nb\ncxxxxx' diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -97,6 +97,8 @@ a2 = bytearray('testing') assert b.readinto(a1) == 1 assert b.readinto(a2) == 4 + exc = raises(TypeError, b.readinto, memoryview(b"hello")) + assert str(exc.value) == "must be read-write buffer, not memoryview" b.close() assert a1 == "h" assert a2 == "elloing" diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -135,6 +135,8 @@ a = bytearray('x' * 10) f = _io.FileIO(self.tmpfile, 'r+') assert f.readinto(a) == 10 + exc = raises(TypeError, f.readinto, memoryview(b"hello")) + assert str(exc.value) == "must be read-write buffer, not memoryview" f.close() assert a == 'a\nb\nc\0\0\0\0\0' # diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py --- a/pypy/objspace/std/bytesobject.py +++ b/pypy/objspace/std/bytesobject.py @@ -443,6 +443,7 @@ return self._value def buffer_w(self, space, flags): + space.check_buf_flags(flags, True) return StringBuffer(self._value) def readbuf_w(self, space): diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py --- a/pypy/objspace/std/memoryobject.py +++ b/pypy/objspace/std/memoryobject.py @@ -34,16 +34,17 @@ an interp-level buffer. """ - def __init__(self, buf): + def __init__(self, obj, buf): assert isinstance(buf, Buffer) + self.obj = obj self.buf = buf def buffer_w(self, space, flags): - return self.buf + return space.buffer_w(self.obj, flags) @staticmethod def descr_new_memoryview(space, w_subtype, w_object): - return W_MemoryView(space.buffer_w(w_object, space.BUF_FULL_RO)) + return W_MemoryView(w_object, space.buffer_w(w_object, space.BUF_FULL_RO)) def _make_descr__cmp(name): def descr__cmp(self, space, w_other): @@ -86,7 +87,7 @@ if size < 0: size = 0 buf = SubBuffer(self.buf, start, size) - return W_MemoryView(buf) + return W_MemoryView(self.obj, buf) def descr_tobytes(self, space): return space.wrap(self.as_str()) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit