localed: normalize empty X11 option values to NULL after parsing
x11_read_data() parses an 'Option "XkbVariant" ""' line in
00-keyboard.conf with strv_split_full(..., EXTRACT_UNQUOTE), which turns
the empty quoted value into a non-NULL empty string rather than NULL.
Since 812aa57d2c ("string-util: beef up string_is_safe()") an empty
string is rejected by string_is_safe() unless STRING_ALLOW_EMPTY is
passed, so x11_context_is_safe() now refuses such a context and
x11_context_verify() discards the whole thing. As a result "localectl
status" reports "X11 Layout: (unset)" even though the file names a valid
layout, and compositors reading org.freedesktop.locale1 (e.g. the SDDM
greeter) fall back to the us layout.
Introduce x11_context_normalize(), suggested by @lionheartyu, which
converts empty strings to NULL while freeing the heap allocation —
unlike x11_context_empty_to_null() which only NULLs the pointer without
freeing. Call it at the end of x11_read_data(), before
x11_context_verify(), so empty option values are treated as unset. This
also keeps x11_context_equal() comparisons consistent with the setter
path (method_set_x11_keyboard) and vconsole_read_data(), which both
store NULL for empty values.
Fixes #43007
This commit is contained in:
@@ -84,6 +84,25 @@ void x11_context_empty_to_null(X11Context *xc) {
|
||||
xc->options = empty_to_null(xc->options);
|
||||
}
|
||||
|
||||
static char* empty_to_null_and_free(char *p) {
|
||||
return isempty(p) ? mfree(p) : p;
|
||||
}
|
||||
|
||||
void x11_context_normalize(X11Context *xc) {
|
||||
assert(xc);
|
||||
|
||||
/* Like x11_context_empty_to_null(), but also frees the heap memory
|
||||
* owned by the fields. Use this for contexts whose strings are
|
||||
* heap-allocated (e.g. x11_read_data()), not for borrowed contexts
|
||||
* such as the one built by method_set_x11_keyboard() from a D-Bus
|
||||
* message. */
|
||||
|
||||
xc->layout = empty_to_null_and_free(xc->layout);
|
||||
xc->model = empty_to_null_and_free(xc->model);
|
||||
xc->variant = empty_to_null_and_free(xc->variant);
|
||||
xc->options = empty_to_null_and_free(xc->options);
|
||||
}
|
||||
|
||||
bool x11_context_is_safe(const X11Context *xc) {
|
||||
assert(xc);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ void x11_context_clear(X11Context *xc);
|
||||
void x11_context_replace(X11Context *dest, X11Context *src);
|
||||
bool x11_context_isempty(const X11Context *xc);
|
||||
void x11_context_empty_to_null(X11Context *xc);
|
||||
void x11_context_normalize(X11Context *xc);
|
||||
bool x11_context_is_safe(const X11Context *xc);
|
||||
bool x11_context_equal(const X11Context *a, const X11Context *b);
|
||||
int x11_context_copy(X11Context *dest, const X11Context *src);
|
||||
|
||||
Reference in New Issue
Block a user