uucore: treat empty locale env vars as unset (fixes #13964) - #14186
uucore: treat empty locale env vars as unset (fixes #13964)#14186MadeNavaneeth wants to merge 2 commits into
Conversation
Empty LC_ALL (or LC_CTYPE, LANG) means 'use the next variable in the cascade', per POSIX. Previously get_locale_from_env parsed the empty string as the C/POSIX locale with ASCII encoding, which caused ls to escape non-ASCII filenames even when LC_CTYPE or LANG specified UTF-8. Fixes uutils#13964
|
sorry but it needs a test |
|
GNU testsuite comparison: |
Merging this PR will not alter performance
Comparing Footnotes
|
| let locale_var = ["LC_ALL", locale_name, "LANG"] | ||
| .iter() | ||
| .find_map(|&key| std::env::var(key).ok()); | ||
| .find_map(|&key| std::env::var(key).ok().filter(|v| !v.is_empty())); |
There was a problem hiding this comment.
| .find_map(|&key| std::env::var(key).ok().filter(|v| !v.is_empty())); | |
| .find_map(|&key| std::env::var(key).ok()) | |
| .filter(|v| !v.is_empty()); |
this is a bit clearer?
There was a problem hiding this comment.
The filter needs to stay inside find_map rather than after it — moving it outside would change the semantics:
In that case, we may have incorrect behavior here:
coreutils/src/uu/uniq/src/uniq.rs
Lines 199 to 205 in 5477f1e
|
Thanks for the suggestion! The filter needs to stay inside // Current (correct): skips empty values, continues to next env var
.find_map(|&key| std::env::var(key).ok().filter(|v| !v.is_empty()))
// Suggested: would match `LC_ALL=""` as the first value, then drop it,
// returning None (POSIX default) instead of falling through to LANG
.find_map(|&key| std::env::var(key).ok())
.filter(|v| !v.is_empty());The Added a test ( |
Fixes #13964
Problem
When
LC_ALLis set to empty string (which POSIX says means "use the next variable in the cascade"),get_locale_from_envparsed it as the C/POSIX locale with ASCII encoding. This causedlsto escape non-ASCII filenames into octal sequences even whenLC_CTYPEorLANGspecified UTF-8.Fix
Treat empty environment variables the same as unset in
get_locale_from_envby filtering out empty values with.filter(|v| !v.is_empty()).Verification
Before (with
LC_ALL=,LANG=uk_UA.UTF-8,LC_CTYPE=uk_UA.UTF-8):After:
This matches GNU
lsbehavior.