Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r97264:215ea348ccb4
Date: 2019-08-26 16:31 +0200
http://bitbucket.org/pypy/pypy/changeset/215ea348ccb4/

Log:    Check for a rare case of someone shrinking the buffer from another
        thread while using it in a read() variant

diff --git a/pypy/module/_file/readinto.py b/pypy/module/_file/readinto.py
--- a/pypy/module/_file/readinto.py
+++ b/pypy/module/_file/readinto.py
@@ -4,6 +4,14 @@
 from rpython.rlib.rposix import c_read
 from rpython.rtyper.lltypesystem import lltype, rffi
 from pypy.module._file.interp_file import is_wouldblock_error, signal_checker
+from pypy.interpreter.error import oefmt
+
+
+def output_slice(space, rwbuffer, target_pos, data):
+    if target_pos + len(data) > rwbuffer.getlength():
+        raise oefmt(space.w_RuntimeError,
+                    "target buffer has shrunk during operation")
+    rwbuffer.setslice(target_pos, data)
 
 
 def direct_readinto(self, w_rwbuffer):
@@ -27,14 +35,14 @@
         MAX_PART = 1024 * 1024    # 1 MB
         while size > MAX_PART:
             data = self.direct_read(MAX_PART)
-            rwbuffer.setslice(target_pos, data)
+            output_slice(self.space, rwbuffer, target_pos, data)
             target_pos += len(data)
             size -= len(data)
             if len(data) != MAX_PART:
                 break
         else:
             data = self.direct_read(size)
-            rwbuffer.setslice(target_pos, data)
+            output_slice(self.space, rwbuffer, target_pos, data)
             target_pos += len(data)
 
     else:
@@ -46,7 +54,7 @@
         initial_size = min(size, stream.count_buffered_bytes())
         if initial_size > 0:
             data = stream.read(initial_size)
-            rwbuffer.setslice(target_pos, data)
+            output_slice(self.space, rwbuffer, target_pos, data)
             target_pos += len(data)
             size -= len(data)
 
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
@@ -101,7 +101,7 @@
             raise oefmt(space.w_TypeError, "%s() should return bytes",
                         methodname)
         data = space.bytes_w(w_data)
-        rwbuffer.setslice(0, data)
+        self.output_slice(space, rwbuffer, 0, data)
         return space.newint(len(data))
 
 W_BufferedIOBase.typedef = TypeDef(
@@ -555,7 +555,7 @@
         remaining = n
         written = 0
         if current_size:
-            result_buffer.setslice(
+            self.output_slice(space, result_buffer,
                 written, self.buffer[self.pos:self.pos + current_size])
             remaining -= current_size
             written += current_size
@@ -600,7 +600,7 @@
             if remaining > 0:
                 if size > remaining:
                     size = remaining
-                result_buffer.setslice(
+                self.output_slice(space, result_buffer,
                     written, self.buffer[self.pos:self.pos + size])
                 self.pos += size
                 written += size
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
@@ -48,7 +48,7 @@
         size = rwbuffer.getlength()
 
         output = self.read(size)
-        rwbuffer.setslice(0, output)
+        self.output_slice(space, rwbuffer, 0, output)
         return space.newint(len(output))
 
     def write_w(self, space, w_data):
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
@@ -389,7 +389,7 @@
                     return space.w_None
                 raise wrap_oserror(space, e,
                                    exception_name='w_IOError')
-            rwbuffer.setslice(0, buf)
+            self.output_slice(space, rwbuffer, 0, buf)
             return space.newint(len(buf))
         else:
             # optimized case: reading more than 64 bytes into a rwbuffer
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -275,6 +275,14 @@
                 else:
                     break
 
+    @staticmethod
+    def output_slice(space, rwbuffer, target_pos, data):
+        if target_pos + len(data) > rwbuffer.getlength():
+            raise oefmt(space.w_RuntimeError,
+                        "target buffer has shrunk during operation")
+        rwbuffer.setslice(target_pos, data)
+
+
 W_IOBase.typedef = TypeDef(
     '_io._IOBase',
     __new__ = generic_new_descr(W_IOBase),
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to