[pypy-commit] pypy refactor-buffer-api: fix validation of buffer writability
bdkearns
noreply at buildbot.pypy.org
Thu Apr 24 03:27:56 CEST 2014
Author: Brian Kearns <bdkearns at 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())
More information about the pypy-commit
mailing list