win: fix error reporting when WTF-8 conversion fails in fs paths - #6
Open
dylan-conway wants to merge 2 commits into
Open
win: fix error reporting when WTF-8 conversion fails in fs paths#6dylan-conway wants to merge 2 commits into
dylan-conway wants to merge 2 commits into
Conversation
fs__realpath_handle() returns -1 with the Win32 last error set for GetFinalPathNameByHandleW failures, but returns the result of uv_utf16_to_wtf8() directly from its tail. That function reports failure with a negative UV error code (UV_ENOMEM) and does not set the thread's last error. fs__realpath() only treated -1 as failure, so a conversion failure fell through to SET_REQ_RESULT(req, 0): the request reported success with req->ptr still NULL, and callers dereferencing the path pointer would crash. Treat any negative return as failure, propagating the UV error code for the conversion case. Also capture GetLastError() before CloseHandle() so the close cannot clobber the failure code.
fs__readlink_handle() mixed two failure conventions: most paths set the Win32 last error and return -1, but the LX symlink branch returned UV_ENOMEM directly and the tail returned uv_utf16_to_wtf8()'s result verbatim, which on failure is a negative UV error code with the thread's last error untouched. All three callers report failures with GetLastError(), so a conversion failure surfaced as whatever stale error happened to be set instead of UV_ENOMEM. Normalize the helper to always set the last error and return -1 on failure, matching its other failure paths. ERROR_OUTOFMEMORY translates back to UV_ENOMEM, and allocation failure is the only way the conversion can fail here since the buffer is sized by uv_utf16_length_as_wtf8() over the same input. Same family of bug as the earlier uv_fs_realpath fix.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughIn ChangesWin32 fs error propagation
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
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.
Summary
Two Windows fs functions mishandle failures of the internal UTF-16 to WTF-8 conversion (
uv_utf16_to_wtf8()). That function reports failure by returning a negative UV error code (UV_ENOMEMwhen its allocation fails) and does not set the thread's Win32 last error — but the surrounding code assumed the "-1 withGetLastError()" convention.uv_fs_realpathreported success with a NULL path pointer.fs__realpath()only treated-1as failure, so a negative UV code from the conversion fell through toSET_REQ_RESULT(req, 0): the request completed withresult == 0whilereq->ptrwas still NULL. Callers that trust the documented contract (success implies a valid path pointer) crash dereferencing it. Fixed by treating any negative return as failure and propagating the UV error code for the conversion case. Also captureGetLastError()beforeCloseHandle()so a succeeding close cannot clobber the failure code.uv_fs_readlink(and the lstat reparse-point path) reported a stale error.fs__readlink_handle()mixed two failure conventions: most paths set the last error and return-1, but the Linux-symlink branch returnedUV_ENOMEMdirectly and the tail returned the conversion result verbatim. All three callers report failures viaGetLastError(), so a conversion failure surfaced as whatever unrelated error happened to be set, instead ofUV_ENOMEM. Fixed by normalizing the helper to always set the last error and return-1(ERROR_OUTOFMEMORYtranslates back toUV_ENOMEM).Both bugs are only reachable when
mallocfails inside the conversion, so they are out-of-memory-only in practice. No behavior change on any success path. Both bugs also exist in upstream libuv v1.x.Test plan
uv_run_tests_a fs_realpathpassesuv_run_tests_a fs_readlink,fs_symlink,fs_symlink_dir,fs_symlink_junctionpassuv_run_tests_a fs_stat_root,fs_lstat_windows_store_apps,fs_unlink_readonlypass (cover the otherfs__readlink_handlecallers)uv_utf16_to_wtf8()can only fail withUV_ENOMEMin these call paths (theUV_ENOBUFSpath requires a caller-supplied buffer; these sites pass a NULL target so the buffer is sized exactly byuv_utf16_length_as_wtf8())