gh-69573: Check the return value of _putch() and _putwch() in msvcrt#154364
Open
gianghungtien wants to merge 1 commit into
Open
gh-69573: Check the return value of _putch() and _putwch() in msvcrt#154364gianghungtien wants to merge 1 commit into
gianghungtien wants to merge 1 commit into
Conversation
…svcrt msvcrt.putch() and msvcrt.putwch() discarded the value returned by the underlying CRT functions, so a failure was silently ignored. The most common case is a process that has no console attached, for example when running under pythonw.exe: _putch() then returns EOF and _putwch() returns WEOF without writing anything. Both functions now raise OSError on failure, which is consistent with ungetch() and ungetwch() in the same module. The CRT sets neither errno nor the Windows last error for this failure, so a generic OSError is raised when no error code is available.
Documentation build overview
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
msvcrt.putch()andmsvcrt.putwch()discarded the value returned by the underlying_putch()/_putwch()CRT functions, so a failed write was silently ignored. This has been the case since the module was written, and it is inconsistent withungetch()/ungetwch()in the same module, which already check their return value and raiseOSError.The most common failure mode is a process with no console attached (for example running under
pythonw.exe, or a child created withDETACHED_PROCESS). In that situation_putch()returnsEOFand_putwch()returnsWEOFwithout writing anything, and the caller had no way to notice.Why not just
PyErr_SetFromErrno()Copying the existing
ungetch()pattern verbatim would have been wrong here. I checked what the UCRT actually reports on this failure, in a process started without a console:The CRT short-circuits on the missing console handle and records no error information at all, so
PyErr_SetFromErrno()on its own would produce a misleading[Errno 0]exception. The fix therefore uses the errno-based message when an error code is available, and falls back to a genericOSError("write to console failed")when it is not.For reference,
_ungetch()succeeds without a console (it only fills a CRT-internal pushback buffer), which is why that function never exposed this problem.Tests
test_putch_without_consoleruns a child process with theDETACHED_PROCESScreation flag (no console at all) and asserts that both functions raiseOSError. It needs noguiresource, so it runs by default. Verified that it fails against an unpatched build (msvcrt.putch() did not raise OSError) and passes with the fix.test_putch/test_putwchcould previously never fail, since the functions ignored all errors. Now that they can raise, they are guarded with arequires_consoleskip so they do not spuriously fail when the test suite itself is run without a console.PCbuild\build.bat -p x64 -c Releasecompiles clean (0 warnings), andpython -m test test_msvcrtpasses (14 run, 3 skipped for theguiresource).Compatibility
This turns a silent no-op into a raised exception, which is a behaviour change. It matches what the issue asks for and what the module already does elsewhere;
putch()/putwch()are documented only as writing to the console, and code that relied on the silent failure was not writing anything anyway. Happy to adjust the scope or the error message if reviewers prefer something different.The
getch()/getche()/getwch()/getwche()family has the same underlying problem, but changing those affects return values rather than just error reporting, so I left them out to keep this change reviewable. Glad to follow up separately if wanted.