mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-01 07:15:32 -04:00
config: pipe_argv_from_value(): plug memory leak
When parsing a key binding with a pipe-argv, we failed to free the argv vector (or to be precise, the strdup:ed entries in the array) when failing to parse the remainder of the binding.
This commit is contained in:
parent
106e14391f
commit
9174e6d79a
1 changed files with 18 additions and 22 deletions
40
config.c
40
config.c
|
|
@ -1645,9 +1645,9 @@ argv_compare(char *const *argv1, char *const *argv2)
|
||||||
* - argv: allocated array containing {"cmd", "arg1", "arg2", NULL}. Caller frees.
|
* - argv: allocated array containing {"cmd", "arg1", "arg2", NULL}. Caller frees.
|
||||||
*/
|
*/
|
||||||
static ssize_t
|
static ssize_t
|
||||||
pipe_argv_from_value(struct context *ctx, char ***argv)
|
pipe_argv_from_value(struct context *ctx, struct argv *argv)
|
||||||
{
|
{
|
||||||
*argv = NULL;
|
argv->args = NULL;
|
||||||
|
|
||||||
if (ctx->value[0] != '[')
|
if (ctx->value[0] != '[')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1661,7 +1661,7 @@ pipe_argv_from_value(struct context *ctx, char ***argv)
|
||||||
size_t pipe_len = pipe_cmd_end - ctx->value - 1;
|
size_t pipe_len = pipe_cmd_end - ctx->value - 1;
|
||||||
char *cmd = xstrndup(&ctx->value[1], pipe_len);
|
char *cmd = xstrndup(&ctx->value[1], pipe_len);
|
||||||
|
|
||||||
if (!tokenize_cmdline(cmd, argv)) {
|
if (!tokenize_cmdline(cmd, &argv->args)) {
|
||||||
LOG_CONTEXTUAL_ERR("syntax error in command line");
|
LOG_CONTEXTUAL_ERR("syntax error in command line");
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1721,7 +1721,7 @@ parse_key_binding_section(struct context *ctx,
|
||||||
const char *const action_map[static action_count],
|
const char *const action_map[static action_count],
|
||||||
struct config_key_binding_list *bindings)
|
struct config_key_binding_list *bindings)
|
||||||
{
|
{
|
||||||
char **pipe_argv;
|
struct argv pipe_argv;
|
||||||
|
|
||||||
ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &pipe_argv);
|
ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &pipe_argv);
|
||||||
if (pipe_remove_len < 0)
|
if (pipe_remove_len < 0)
|
||||||
|
|
@ -1736,8 +1736,8 @@ parse_key_binding_section(struct context *ctx,
|
||||||
|
|
||||||
/* Unset binding */
|
/* Unset binding */
|
||||||
if (strcasecmp(ctx->value, "none") == 0) {
|
if (strcasecmp(ctx->value, "none") == 0) {
|
||||||
remove_action_from_key_bindings_list(bindings, action, pipe_argv);
|
remove_action_from_key_bindings_list(bindings, action, pipe_argv.args);
|
||||||
free(pipe_argv);
|
free_argv(&pipe_argv);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1746,12 +1746,12 @@ parse_key_binding_section(struct context *ctx,
|
||||||
has_key_binding_collisions(
|
has_key_binding_collisions(
|
||||||
ctx, action, action_map, bindings, &key_combos))
|
ctx, action, action_map, bindings, &key_combos))
|
||||||
{
|
{
|
||||||
free(pipe_argv);
|
free_argv(&pipe_argv);
|
||||||
free_key_combo_list(&key_combos);
|
free_key_combo_list(&key_combos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_action_from_key_bindings_list(bindings, action, pipe_argv);
|
remove_action_from_key_bindings_list(bindings, action, pipe_argv.args);
|
||||||
|
|
||||||
/* Emit key bindings */
|
/* Emit key bindings */
|
||||||
size_t ofs = bindings->count;
|
size_t ofs = bindings->count;
|
||||||
|
|
@ -1767,9 +1767,7 @@ parse_key_binding_section(struct context *ctx,
|
||||||
.modifiers = combo->modifiers,
|
.modifiers = combo->modifiers,
|
||||||
.sym = combo->sym,
|
.sym = combo->sym,
|
||||||
.pipe = {
|
.pipe = {
|
||||||
.argv = {
|
.argv = pipe_argv,
|
||||||
.args = pipe_argv,
|
|
||||||
},
|
|
||||||
.master_copy = first,
|
.master_copy = first,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -1784,7 +1782,7 @@ parse_key_binding_section(struct context *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_CONTEXTUAL_ERR("not a valid action: %s", ctx->key);
|
LOG_CONTEXTUAL_ERR("not a valid action: %s", ctx->key);
|
||||||
free(pipe_argv);
|
free_argv(&pipe_argv);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2097,7 +2095,7 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
const char *key = ctx->key;
|
const char *key = ctx->key;
|
||||||
const char *value = ctx->value;
|
const char *value = ctx->value;
|
||||||
|
|
||||||
char **pipe_argv;
|
struct argv pipe_argv;
|
||||||
|
|
||||||
ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &pipe_argv);
|
ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &pipe_argv);
|
||||||
if (pipe_remove_len < 0)
|
if (pipe_remove_len < 0)
|
||||||
|
|
@ -2125,7 +2123,7 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
binding->action = BIND_ACTION_NONE;
|
binding->action = BIND_ACTION_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(pipe_argv);
|
free_argv(&pipe_argv);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2133,7 +2131,7 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
if (!value_to_mouse_combos(ctx, &key_combos) ||
|
if (!value_to_mouse_combos(ctx, &key_combos) ||
|
||||||
has_mouse_binding_collisions(ctx, &key_combos))
|
has_mouse_binding_collisions(ctx, &key_combos))
|
||||||
{
|
{
|
||||||
free(pipe_argv);
|
free_argv(&pipe_argv);
|
||||||
free_key_combo_list(&key_combos);
|
free_key_combo_list(&key_combos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -2143,9 +2141,9 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
struct config_mouse_binding *binding = &conf->bindings.mouse.arr[i];
|
struct config_mouse_binding *binding = &conf->bindings.mouse.arr[i];
|
||||||
|
|
||||||
if (binding->action == action &&
|
if (binding->action == action &&
|
||||||
((binding->pipe.argv.args == NULL && pipe_argv == NULL) ||
|
((binding->pipe.argv.args == NULL && pipe_argv.args == NULL) ||
|
||||||
(binding->pipe.argv.args != NULL && pipe_argv != NULL &&
|
(binding->pipe.argv.args != NULL && pipe_argv.args != NULL &&
|
||||||
argv_compare(binding->pipe.argv.args, pipe_argv) == 0)))
|
argv_compare(binding->pipe.argv.args, pipe_argv.args) == 0)))
|
||||||
{
|
{
|
||||||
if (binding->pipe.master_copy)
|
if (binding->pipe.master_copy)
|
||||||
free_argv(&binding->pipe.argv);
|
free_argv(&binding->pipe.argv);
|
||||||
|
|
@ -2169,9 +2167,7 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
.button = combo->m.button,
|
.button = combo->m.button,
|
||||||
.count = combo->m.count,
|
.count = combo->m.count,
|
||||||
.pipe = {
|
.pipe = {
|
||||||
.argv = {
|
.argv = pipe_argv,
|
||||||
.args = pipe_argv,
|
|
||||||
},
|
|
||||||
.master_copy = first,
|
.master_copy = first,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -2185,7 +2181,7 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_CONTEXTUAL_ERR("not a valid option: %s", key);
|
LOG_CONTEXTUAL_ERR("not a valid option: %s", key);
|
||||||
free(pipe_argv);
|
free_argv(&pipe_argv);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue