tokenize: strdup() each individual argv

Instead of referencing the un-tokenized “raw” command string, strdup()
each argv. This way, the input string can be ‘const’.
This commit is contained in:
Daniel Eklöf 2021-06-20 14:17:31 +02:00
parent 7632e16e36
commit 42ec264075
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 56 additions and 38 deletions

View file

@ -501,29 +501,59 @@ str_to_pt_or_px(const char *s, struct pt_or_px *res, struct config *conf,
return true; return true;
} }
static void NOINLINE
free_spawn_template(struct config_spawn_template *template)
{
if (template->argv == NULL)
return;
for (char **argv = template->argv; *argv != NULL; argv++)
free(*argv);
free(template->argv);
template->argv = NULL;
}
static void NOINLINE
clone_spawn_template(struct config_spawn_template *dst,
const struct config_spawn_template *src)
{
if (src->argv == NULL) {
dst->argv = NULL;
return;
}
size_t count = 0;
for (char **argv = src->argv; *argv != NULL; argv++)
count++;
dst->argv = xmalloc((count + 1) * sizeof(dst->argv[0]));
for (char **argv_src = src->argv, **argv_dst = dst->argv;
*argv_src != NULL; argv_src++,
argv_dst++)
{
*argv_dst = xstrdup(*argv_src);
}
dst->argv[count] = NULL;
}
static bool NOINLINE static bool NOINLINE
str_to_spawn_template(struct config *conf, str_to_spawn_template(struct config *conf,
const char *s, struct config_spawn_template *template, const char *s, struct config_spawn_template *template,
const char *path, int lineno, const char *section, const char *path, int lineno, const char *section,
const char *key) const char *key)
{ {
free(template->raw_cmd); free_spawn_template(template);
free(template->argv);
template->raw_cmd = NULL;
template->argv = NULL;
char *raw_cmd = xstrdup(s);
char **argv = NULL; char **argv = NULL;
if (!tokenize_cmdline(raw_cmd, &argv)) { if (!tokenize_cmdline(s, &argv)) {
LOG_AND_NOTIFY_ERR( LOG_AND_NOTIFY_ERR(
"%s:%d: [%s]: %s: syntax error in command line", "%s:%d: [%s]: %s: syntax error in command line",
path, lineno, section, key); path, lineno, section, key);
return false; return false;
} }
template->raw_cmd = raw_cmd;
template->argv = argv; template->argv = argv;
return true; return true;
} }
@ -2594,7 +2624,6 @@ config_load(struct config *conf, const char *conf_path,
.urgent = false, .urgent = false,
.notify = false, .notify = false,
.command = { .command = {
.raw_cmd = NULL,
.argv = NULL, .argv = NULL,
}, },
.command_focused = false, .command_focused = false,
@ -2671,7 +2700,6 @@ config_load(struct config *conf, const char *conf_path,
.selection_target = SELECTION_TARGET_PRIMARY, .selection_target = SELECTION_TARGET_PRIMARY,
.hold_at_exit = false, .hold_at_exit = false,
.notify = { .notify = {
.raw_cmd = NULL,
.argv = NULL, .argv = NULL,
}, },
@ -2717,12 +2745,9 @@ config_load(struct config *conf, const char *conf_path,
} }
} }
conf->notify.raw_cmd = xstrdup( tokenize_cmdline("notify-send -a ${app-id} -i ${app-id} ${title} ${body}",
"notify-send -a ${app-id} -i ${app-id} ${title} ${body}"); &conf->notify.argv);
tokenize_cmdline(conf->notify.raw_cmd, &conf->notify.argv); tokenize_cmdline("xdg-open ${url}", &conf->url.launch.argv);
conf->url.launch.raw_cmd = xstrdup("xdg-open ${url}");
tokenize_cmdline(conf->url.launch.raw_cmd, &conf->url.launch.argv);
static const wchar_t *url_protocols[] = { static const wchar_t *url_protocols[] = {
L"http://", L"http://",
@ -2847,13 +2872,6 @@ config_override_apply(struct config *conf, config_override_t *overrides, bool er
return true; return true;
} }
static void NOINLINE
free_spawn_template(struct config_spawn_template *template)
{
free(template->raw_cmd);
free(template->argv);
}
static void NOINLINE static void NOINLINE
binding_pipe_free(struct config_binding_pipe *pipe) binding_pipe_free(struct config_binding_pipe *pipe)
{ {

View file

@ -63,7 +63,6 @@ DEFINE_LIST(struct config_mouse_binding);
typedef tll(char *) config_override_t; typedef tll(char *) config_override_t;
struct config_spawn_template { struct config_spawn_template {
char *raw_cmd;
char **argv; char **argv;
}; };

View file

@ -293,9 +293,7 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
char **shell_argv = NULL; char **shell_argv = NULL;
if (argc == 0) { if (argc == 0) {
char *shell_copy = xstrdup(conf_shell); if (!tokenize_cmdline(conf_shell, &_shell_argv)) {
if (!tokenize_cmdline(shell_copy, &_shell_argv)) {
free(shell_copy);
(void)!write(fork_pipe[1], &errno, sizeof(errno)); (void)!write(fork_pipe[1], &errno, sizeof(errno));
_exit(0); _exit(0);
} }

View file

@ -6,9 +6,10 @@
#define LOG_MODULE "tokenize" #define LOG_MODULE "tokenize"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "log.h" #include "log.h"
#include "xmalloc.h"
static bool static bool
push_argv(char ***argv, size_t *size, char *arg, size_t *argc) push_argv(char ***argv, size_t *size, const char *arg, size_t len, size_t *argc)
{ {
if (arg != NULL && arg[0] == '%') if (arg != NULL && arg[0] == '%')
return true; return true;
@ -24,21 +25,23 @@ push_argv(char ***argv, size_t *size, char *arg, size_t *argc)
*size = new_size; *size = new_size;
} }
(*argv)[(*argc)++] = arg; (*argv)[(*argc)++] = arg != NULL ? xstrndup(arg, len) : NULL;
return true; return true;
} }
bool bool
tokenize_cmdline(char *cmdline, char ***argv) tokenize_cmdline(const char *cmdline, char ***argv)
{ {
*argv = NULL; *argv = NULL;
size_t argv_size = 0; size_t argv_size = 0;
const char *final_end = cmdline + strlen(cmdline) + 1;
bool first_token_is_quoted = cmdline[0] == '"' || cmdline[0] == '\''; bool first_token_is_quoted = cmdline[0] == '"' || cmdline[0] == '\'';
char delim = first_token_is_quoted ? cmdline[0] : ' '; char delim = first_token_is_quoted ? cmdline[0] : ' ';
char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0]; const char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0];
char *search_start = p; const char *search_start = p;
size_t idx = 0; size_t idx = 0;
while (*p != '\0') { while (*p != '\0') {
@ -51,8 +54,8 @@ tokenize_cmdline(char *cmdline, char ***argv)
return false; return false;
} }
if (!push_argv(argv, &argv_size, p, &idx) || if (!push_argv(argv, &argv_size, p, final_end - p, &idx) ||
!push_argv(argv, &argv_size, NULL, &idx)) !push_argv(argv, &argv_size, NULL, 0, &idx))
{ {
goto err; goto err;
} else } else
@ -68,9 +71,9 @@ tokenize_cmdline(char *cmdline, char ***argv)
continue; continue;
} }
*end = '\0'; //*end = '\0';
if (!push_argv(argv, &argv_size, p, &idx)) if (!push_argv(argv, &argv_size, p, end - p, &idx))
goto err; goto err;
p = end + 1; p = end + 1;
@ -88,7 +91,7 @@ tokenize_cmdline(char *cmdline, char ***argv)
search_start = p; search_start = p;
} }
if (!push_argv(argv, &argv_size, NULL, &idx)) if (!push_argv(argv, &argv_size, NULL, 0, &idx))
goto err; goto err;
return true; return true;

View file

@ -2,4 +2,4 @@
#include <stdbool.h> #include <stdbool.h>
bool tokenize_cmdline(char *cmdline, char ***argv); bool tokenize_cmdline(const char *cmdline, char ***argv);