fix(encoding): bound non-codecvt narrow/widen by str_size#1359
Merged
Conversation
The non-codecvt branches of narrow_impl/widen_impl discarded str_size and relied on std::wcsrtombs/std::mbsrtowcs converting up to a NUL terminator. This was wrong for the size-taking overloads (narrow(const wchar_t*, size), the string_view overloads, etc.): a view into the middle of a buffer converted the entire remainder, a view over a non-NUL-terminated buffer read out of bounds, and embedded NULs truncated the result. The codecvt path already handled this correctly via to_bytes(str, str + str_size). Copy the input into a local NUL-terminated buffer of exactly str_size characters so the conversion is bounded. Embedded NULs still terminate the C-style conversion early; this is documented as a best-effort limitation. This path becomes the default under C++26 (CLI11_HAS_CODECVT is 0 when CLI11_CPP26 is set), so correctness here matters increasingly. Add regression tests (Encoding: WidenSize / NarrowSize) that convert a prefix of a longer buffer and a non-NUL-terminated buffer; they pass under both the codecvt and non-codecvt (-DCLI11_HAS_CODECVT=0) paths. Assisted-by: ClaudeCode:claude-opus-4-8
Collaborator
Author
|
I'm not on Windows, but the tests pass, so will undraft. |
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.
🤖 AI text below 🤖
Bug
In
include/CLI/impl/Encoding_inl.hpp, the non-codecvt branches ofnarrow_impl/widen_impldid(void)str_size;and relied onstd::wcsrtombs/std::mbsrtowcsconverting up to a NUL terminator. That is fine for thestd::wstring/null-terminated overloads, but wrong for the size-taking overloads (narrow(const wchar_t *, std::size_t), the C++17narrow(std::wstring_view)/widen(std::string_view), etc.):str_sizecharacters.The codecvt path already handled all of this correctly via
to_bytes(str, str + str_size). This non-codecvt path becomes the default under C++26 (CLI11_HAS_CODECVTis 0 whenCLI11_CPP26is set, perinclude/CLI/Macros.hpp), so it matters increasingly.Fix
In the non-codecvt branches, copy the input into a local, NUL-terminated buffer of exactly
str_sizecharacters and convert from that, so the conversion is bounded bystr_sizeand never reads past the buffer. The existing localescope_guardbehavior and error reporting are preserved (offsets now reported relative to the local copy). C++11-compatible. Embedded NULs within the firststr_sizecharacters still terminate the C-style conversion early; this is documented in a comment as a best-effort limitation.Testing (dual-path)
Added
Encoding: WidenSize/Encoding: NarrowSizeregression tests intests/EncodingTest.cppthat:widen(longer.c_str(), 6)/narrow(longer.c_str(), 6)) and assert only the prefix is converted;str_sizechars (would read OOB under the old code).Both the default (codecvt) build and a
-DCMAKE_CXX_FLAGS=-DCLI11_HAS_CODECVT=0build were configured and run;EncodingTestpasses in both. The macro override was confirmed to select the non-codecvt branch (preprocessed output useswcsrtombs/mbsrtowcsrather thanto_bytes).Part of #1357