Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcc6bc4c

Browse files
authored
GH-134453: Fix subprocess memoryview input handling on POSIX (GH-134949)
Fix inconsistent subprocess.Popen.communicate() behavior between Windowsand POSIX when using memoryview objects with non-byte elements as input.On POSIX systems, the code was incorrectly comparing bytes written againstelement count instead of byte count, causing data truncation for largeinputs with non-byte element types.Changes:- Cast memoryview inputs to byte view when input is already a memoryview- Fix progress tracking to use len(input_view) instead of len(self._input)- Add comprehensive test coverage for memoryview inputs🤖 Generated with [Claude Code](https://claude.ai/code)Co-Authored-By: Claude <noreply@anthropic.com>* old-man-yells-at-ReST* Update 2025-05-30-18-37-44.gh-issue-134453.kxkA-o.rst* assertIsNone review feedback* fix memoryview_nonbytes test to fail without our fix on main, and have a nicer error.Thanks to Peter Bierma@ZeroIntensity for the code review.
1 parent526d7a8 commitcc6bc4c

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

‎Lib/subprocess.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,10 @@ def _communicate(self, input, endtime, orig_timeout):
21022102
self._save_input(input)
21032103

21042104
ifself._input:
2105-
input_view=memoryview(self._input)
2105+
ifnotisinstance(self._input,memoryview):
2106+
input_view=memoryview(self._input)
2107+
else:
2108+
input_view=self._input.cast("b")# byte input required
21062109

21072110
with_PopenSelector()asselector:
21082111
ifself.stdinandnotself.stdin.closedandself._input:
@@ -2138,7 +2141,7 @@ def _communicate(self, input, endtime, orig_timeout):
21382141
selector.unregister(key.fileobj)
21392142
key.fileobj.close()
21402143
else:
2141-
ifself._input_offset>=len(self._input):
2144+
ifself._input_offset>=len(input_view):
21422145
selector.unregister(key.fileobj)
21432146
key.fileobj.close()
21442147
elifkey.fileobjin (self.stdout,self.stderr):

‎Lib/test/test_subprocess.py‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,48 @@ def test_communicate(self):
957957
self.assertEqual(stdout,b"banana")
958958
self.assertEqual(stderr,b"pineapple")
959959

960+
deftest_communicate_memoryview_input(self):
961+
# Test memoryview input with byte elements
962+
test_data=b"Hello, memoryview!"
963+
mv=memoryview(test_data)
964+
p=subprocess.Popen([sys.executable,"-c",
965+
'import sys; sys.stdout.write(sys.stdin.read())'],
966+
stdin=subprocess.PIPE,
967+
stdout=subprocess.PIPE)
968+
self.addCleanup(p.stdout.close)
969+
self.addCleanup(p.stdin.close)
970+
(stdout,stderr)=p.communicate(mv)
971+
self.assertEqual(stdout,test_data)
972+
self.assertIsNone(stderr)
973+
974+
deftest_communicate_memoryview_input_nonbyte(self):
975+
# Test memoryview input with non-byte elements (e.g., int32)
976+
# This tests the fix for gh-134453 where non-byte memoryviews
977+
# had incorrect length tracking on POSIX
978+
importarray
979+
# Create an array of 32-bit integers that's large enough to trigger
980+
# the chunked writing behavior (> PIPE_BUF)
981+
pipe_buf=getattr(select,'PIPE_BUF',512)
982+
# Each 'i' element is 4 bytes, so we need more than pipe_buf/4 elements
983+
# Add some extra to ensure we exceed the buffer size
984+
num_elements=pipe_buf+1
985+
test_array=array.array('i', [0x64306f66for_inrange(num_elements)])
986+
expected_bytes=test_array.tobytes()
987+
mv=memoryview(test_array)
988+
989+
p=subprocess.Popen([sys.executable,"-c",
990+
'import sys; '
991+
'data = sys.stdin.buffer.read(); '
992+
'sys.stdout.buffer.write(data)'],
993+
stdin=subprocess.PIPE,
994+
stdout=subprocess.PIPE)
995+
self.addCleanup(p.stdout.close)
996+
self.addCleanup(p.stdin.close)
997+
(stdout,stderr)=p.communicate(mv)
998+
self.assertEqual(stdout,expected_bytes,
999+
msg=f"{len(stdout)=} =?{len(expected_bytes)=}")
1000+
self.assertIsNone(stderr)
1001+
9601002
deftest_communicate_timeout(self):
9611003
p=subprocess.Popen([sys.executable,"-c",
9621004
'import sys,os,time;'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixed:func:`subprocess.Popen.communicate` ``input=`` handling of:class:`memoryview`
2+
instances that were non-byte shaped on POSIX platforms. Those are now properly
3+
cast to a byte shaped view instead of truncating the input. Windows platforms
4+
did not have this bug.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp