Skip to content

log: Fix C-locale UTF-8 splitting and out-of-range codepoints - #1166

Open
seks99x wants to merge 2 commits into
RsyncProject:masterfrom
seks99x:fix-c-locale-utf8-log
Open

seks99x wants to merge 2 commits into
RsyncProject:masterfrom
seks99x:fix-c-locale-utf8-log

Conversation

@seks99x

@seks99x seks99x commented Nov 11, 2026

Copy link
Copy Markdown
Member

Fixes #1162

Description:
When running in the C/POSIX locale (MB_CUR_MAX == 1) or without mbrtowc(), mbrtowc() rejects all bytes >= 0x80. The single-byte fallback in filtered_char_len() then leaves leading bytes >= 0xa0 raw while escaping 0x80..0x9f continuation bytes as C1 controls, splitting valid UTF-8 characters like U+00DF (0xc3 0x9f).
Add utf8_char_len() as a fallback when MB_CUR_MAX == 1 or mbrtowc() is unavailable so valid UTF-8 sequences are preserved intact and UTF-8 C1 controls (U+0080..U+009F) are escaped, while invalid, incomplete, overlong, surrogate, or > U+10FFFF sequences fall back to per-byte filtering. Also reject surrogates and codepoints > U+10FFFF from mbrtowc() in locale_char_len(), and expand output-control-chars_test.py to cover C-locale and malformed UTF-8 edge cases.

When running in the 7-bit C/POSIX locale (MB_CUR_MAX == 1, such as in
minimal containers without locale data installed) or without mbrtowc(),
mbrtowc() rejects all bytes >= 0x80. The single-byte fallback in
filtered_char_len() then passed leading bytes >= 0xa0 through raw while
escaping continuation bytes in 0x80..0x9f as C1 controls, splitting
valid UTF-8 characters like U+00DF (0xc3 0x9f) into a raw 0xc3 byte
followed by an octal escape for 0x9f.

Add a built-in UTF-8 decoder fallback (utf8_char_len) when MB_CUR_MAX == 1
or mbrtowc() is unavailable so valid UTF-8 sequences are preserved intact
and UTF-8 C1 controls (U+0080..U+009F) are still escaped, while invalid,
incomplete, overlong, surrogate, or > U+10FFFF sequences fall back to
per-byte filtering. Also reject surrogates and codepoints > U+10FFFF from
mbrtowc() so 4-byte sequences above U+10FFFF cannot smuggle raw 0x80..0x9f
continuation bytes under permissive libc implementations.
On platforms that do not define __STDC_ISO_10646__ (such as NetBSD and
Solaris), wchar_t in non-UTF-8 locales like ja_JP.eucJP stores packed
codeset bits that exceed 0x10ffff rather than UCS-4 codepoints. Guard
the surrogate and > U+10FFFF check on mbrtowc() output with
__STDC_ISO_10646__ so valid EUC-JP multibyte characters are not
rejected on BSD and Solaris.
@seks99x
seks99x force-pushed the fix-c-locale-utf8-log branch from 12bfed7 to e613028 Compare November 11, 2026 17:37
@seks99x

seks99x commented Nov 11, 2026

Copy link
Copy Markdown
Member Author

@phmarek test please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logfile corrupted by bad filenames

1 participant