-
-
Notifications
You must be signed in to change notification settings - Fork 32.7k
bpo-31178: Avoid concatenating bytes with str in subprocess error #3066
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8f8b86a
c277e29
df3e1d3
7410ae2
f007582
f061ff1
7a36648
2707615
8634c2b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1307,15 +1307,18 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, | |
try: | ||
exception_name, hex_errno, err_msg = ( | ||
errpipe_data.split(b':', 2)) | ||
# The encoding here should match the encoding | ||
# written in by the subprocess implementations | ||
# like _posixsubprocess | ||
err_msg = err_msg.decode() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please keep .decode(errors="surrogatepass"). The modified code is called when something goes wrong. I would prefer to avoid a decoding error if possible. It can happen that something writes junk into the pipe. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But why you expect that this junk is UTF-8 with allowed surrogates? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I'm not sure where you're expecting this junk from. If the split managed to succeed then the data is likely written in by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I've added UnicodeError to the except block there, so in case this actually happens it'll fall through and simply put the repr of the bytes in the error message. |
||
except ValueError: | ||
exception_name = b'SubprocessError' | ||
hex_errno = b'0' | ||
err_msg = (b'Bad exception data from child: ' + | ||
repr(errpipe_data)) | ||
err_msg = 'Bad exception data from child: {!r}'.format( | ||
bytes(errpipe_data)) | ||
child_exception_type = getattr( | ||
builtins, exception_name.decode('ascii'), | ||
SubprocessError) | ||
err_msg = err_msg.decode(errors="surrogatepass") | ||
if issubclass(child_exception_type, OSError) and hex_errno: | ||
errno_num = int(hex_errno, 16) | ||
child_exec_never_called = (err_msg == "noexec") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fix string concatenation bug in rare error path in the subprocess module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To simplify the code, I suggest to decode pipe data before the try:
Since both code paths decode anyway. It would allow to work on Unicode rather than bytes, which is more convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But decoding can fail itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how .decode(errors="surrogatepass") can fail. MemoryError, maybe? If you are out of memory, everything will fail anyway :-)
See the current code, we already decode, I only suggest to move the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serhiy-storchaka, @ammaraskar: Oh sorry, I was thinking at surrogateescape, whereas it's surrogatepeass. Please replace .decode('surrogatepass') with .decode('surrogateescape'), so decoding cannot fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you read my comment here? #3066 (comment)
In the case where _posixsubprocess writes to the errpipe, there should be nothing in there that can't be decoded. And if there is junk in there that wasn't written by _posixsubproccess, the decode will fail and it'll print out the appropriate message saying
Bad exception data from child: b'UNDECODABLE:MESS:HERE'