[pypy-commit] pypy py3k: act more like CPython's _PySequence_BytesToCharpArray: trigger MemoryErrors

pjenvey noreply at buildbot.pypy.org
Wed Apr 23 03:29:17 CEST 2014


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r70879:eb519320687f
Date: 2014-04-22 18:25 -0700
http://bitbucket.org/pypy/pypy/changeset/eb519320687f/

Log:	act more like CPython's _PySequence_BytesToCharpArray: trigger
	MemoryErrors with large __len__ results (unpackiterable doesn't).
	fixes test_capi.test_seq_bytes_to_charp_array

diff --git a/pypy/module/_posixsubprocess/interp_subprocess.py b/pypy/module/_posixsubprocess/interp_subprocess.py
--- a/pypy/module/_posixsubprocess/interp_subprocess.py
+++ b/pypy/module/_posixsubprocess/interp_subprocess.py
@@ -86,6 +86,13 @@
     return result
 
 
+def seqstr2charpp(space, w_seqstr):
+    """Sequence of bytes -> char**, NULL terminated"""
+    w_iter = space.iter(w_seqstr)
+    return rffi.liststr2charpp([space.bytes0_w(space.next(w_iter))
+                                for i in range(space.len_w(w_seqstr))])
+
+
 @unwrap_spec(p2cread=int, p2cwrite=int, c2pread=int, c2pwrite=int,
              errread=int, errwrite=int, errpipe_read=int, errpipe_write=int,
              restore_signals=int, call_setsid=int)
@@ -135,19 +142,16 @@
     # These conversions are done in the parent process to avoid allocating
     # or freeing memory in the child process.
     try:
-        exec_array = [space.bytes0_w(w_item)
-                      for w_item in space.listview(w_executable_list)]
-        l_exec_array = rffi.liststr2charpp(exec_array)
+        l_exec_array = seqstr2charpp(space, w_executable_list)
 
         if not space.is_none(w_process_args):
-            argv = [space.fsencode_w(w_item)
-                    for w_item in space.listview(w_process_args)]
+            w_iter = space.iter(w_process_args)
+            argv = [space.fsencode_w(space.next(w_iter))
+                    for i in range(space.len_w(w_process_args))]
             l_argv = rffi.liststr2charpp(argv)
 
         if not space.is_none(w_env_list):
-            envp = [space.bytes0_w(w_item)
-                    for w_item in space.listview(w_env_list)]
-            l_envp = rffi.liststr2charpp(envp)
+            l_envp = seqstr2charpp(space, w_env_list)
 
         l_fds_to_keep = lltype.malloc(rffi.CArrayPtr(rffi.LONG).TO,
                                       len(fds_to_keep) + 1, flavor='raw')
diff --git a/pypy/module/_posixsubprocess/test/test_subprocess.py b/pypy/module/_posixsubprocess/test/test_subprocess.py
--- a/pypy/module/_posixsubprocess/test/test_subprocess.py
+++ b/pypy/module/_posixsubprocess/test/test_subprocess.py
@@ -57,3 +57,18 @@
             parent_pgid = os.getpgid(os.getpid())
             child_pgid = int(output)
             assert parent_pgid != child_pgid
+
+    def test_cpython_issue15736(self):
+        import _posixsubprocess
+        import sys
+        n = 0
+        class Z(object):
+            def __len__(self):
+                return sys.maxsize + n
+            def __getitem__(self, i):
+                return b'x'
+        raises(MemoryError, _posixsubprocess.fork_exec,
+               1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
+        n = 1
+        raises(OverflowError, _posixsubprocess.fork_exec,
+               1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)


More information about the pypy-commit mailing list