mirror of
https://github.com/swaywm/sway.git
synced 2026-06-13 14:33:19 -04:00
tree/load_layout: validate window_type literals strictly
Anchored ^name$ and bare names are accepted; everything else, including regex alternation, returns a clear error instead of silently falling through to ATOM_LAST.
This commit is contained in:
parent
0bb4aba044
commit
93931c37a6
2 changed files with 43 additions and 21 deletions
|
|
@ -426,7 +426,13 @@ runtime.
|
|||
*class*, *instance*, *title*, *window_role*, and *window_type* keys
|
||||
(which target xwayland views), each *swallows* entry may include
|
||||
*app_id* to match Wayland views. The *machine* key is logged and
|
||||
ignored. All values are PCRE2 regex strings.
|
||||
ignored. *class*, *instance*, *title*, *window_role* and *app_id*
|
||||
are PCRE2 regex strings. *window_type* must be a literal atom name
|
||||
(*normal*, *dialog*, *utility*, *toolbar*, *splash*, *menu*,
|
||||
*dropdown_menu*, *popup_menu*, *tooltip*, *notification*); the
|
||||
i3-save-tree anchored form _^name$_ is accepted, but regex
|
||||
alternation such as _^(normal|dialog)$_ is rejected, split such
|
||||
patterns into multiple swallows entries (which match as OR).
|
||||
|
||||
A minimal example targeting one Wayland and one xwayland window in
|
||||
a vertical split:
|
||||
|
|
|
|||
|
|
@ -227,27 +227,38 @@ static bool append_bare(char **buf, const char *key, const char *value) {
|
|||
return written >= 0;
|
||||
}
|
||||
|
||||
// i3-save-tree emits window_type as a regex-anchored enum name like
|
||||
// "^normal$". The criteria parser treats window_type as a bare enum token,
|
||||
// not a regex, so the anchored form fails. Strip a single leading ^ and a
|
||||
// single trailing $ before passing through.
|
||||
static char *unanchor_enum(const char *value) {
|
||||
// window_type is parsed as an enum, not a regex. Accept i3-save-tree's
|
||||
// "^name$" form and bare names; reject anything else (including alternation)
|
||||
// rather than letting the criteria parser silently fall through to ATOM_LAST.
|
||||
static const char *known_window_types[] = {
|
||||
"normal", "dialog", "utility", "toolbar", "splash", "menu",
|
||||
"dropdown_menu", "popup_menu", "tooltip", "notification", NULL,
|
||||
};
|
||||
|
||||
static char *parse_window_type_value(const char *value, char **error_out) {
|
||||
size_t n = strlen(value);
|
||||
size_t start = 0;
|
||||
size_t end = n;
|
||||
if (n > 0 && value[0] == '^') {
|
||||
start = 1;
|
||||
}
|
||||
if (end > start && value[end - 1] == '$') {
|
||||
end--;
|
||||
}
|
||||
char *out = malloc(end - start + 1);
|
||||
if (!out) {
|
||||
size_t start = (n > 0 && value[0] == '^') ? 1 : 0;
|
||||
size_t end = (n > start && value[n - 1] == '$') ? n - 1 : n;
|
||||
size_t bare_len = end - start;
|
||||
char *bare = malloc(bare_len + 1);
|
||||
if (!bare) {
|
||||
*error_out = format_str("append_layout: out of memory");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(out, value + start, end - start);
|
||||
out[end - start] = '\0';
|
||||
return out;
|
||||
memcpy(bare, value + start, bare_len);
|
||||
bare[bare_len] = '\0';
|
||||
for (int i = 0; known_window_types[i]; i++) {
|
||||
if (strcasecmp(bare, known_window_types[i]) == 0) {
|
||||
return bare;
|
||||
}
|
||||
}
|
||||
*error_out = format_str("append_layout: window_type %s is not a "
|
||||
"supported literal value (use one of: normal, dialog, "
|
||||
"utility, toolbar, splash, menu, dropdown_menu, popup_menu, "
|
||||
"tooltip, notification; regex alternation is not supported, "
|
||||
"split into multiple swallow entries instead)", value);
|
||||
free(bare);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// app_id is a sway extension over i3's swallows schema; machine is ignored.
|
||||
|
|
@ -287,8 +298,13 @@ static struct criteria *build_swallow_criteria(struct json_object *entry,
|
|||
"append_layout: swallows.window_type is not a string");
|
||||
return NULL;
|
||||
}
|
||||
char *bare = unanchor_enum(json_object_get_string(wt));
|
||||
if (!bare || !append_bare(&body, "window_type", bare)) {
|
||||
char *bare = parse_window_type_value(json_object_get_string(wt),
|
||||
error_out);
|
||||
if (!bare) {
|
||||
free(body);
|
||||
return NULL;
|
||||
}
|
||||
if (!append_bare(&body, "window_type", bare)) {
|
||||
free(bare);
|
||||
free(body);
|
||||
*error_out = format_str("append_layout: out of memory");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue