mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 13:37:12 +00:00
Instead of forbidding invalid session names, sanitize them.
This commit is contained in:
@ -70,13 +70,14 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *current = cmdq_get_current(item);
|
struct cmd_find_state *current = cmdq_get_current(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct client *c = cmdq_get_client(item);
|
struct client *c = cmdq_get_client(item);
|
||||||
struct session *s, *as, *groupwith;
|
struct session *s, *as, *groupwith = NULL;
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct termios tio, *tiop;
|
struct termios tio, *tiop;
|
||||||
struct session_group *sg;
|
struct session_group *sg = NULL;
|
||||||
const char *errstr, *template, *group, *prefix, *tmp;
|
const char *errstr, *template, *group, *tmp;
|
||||||
char *cause, *cwd = NULL, *cp, *newname = NULL;
|
char *cause, *cwd = NULL, *cp, *newname = NULL;
|
||||||
|
char *name, *prefix = NULL;
|
||||||
int detached, already_attached, is_control = 0;
|
int detached, already_attached, is_control = 0;
|
||||||
u_int sx, sy, dsx, dsy;
|
u_int sx, sy, dsx, dsy;
|
||||||
struct spawn_context sc;
|
struct spawn_context sc;
|
||||||
@ -98,11 +99,9 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
tmp = args_get(args, 's');
|
tmp = args_get(args, 's');
|
||||||
if (tmp != NULL) {
|
if (tmp != NULL) {
|
||||||
newname = format_single(item, tmp, c, NULL, NULL, NULL);
|
name = format_single(item, tmp, c, NULL, NULL, NULL);
|
||||||
if (!session_check_name(newname)) {
|
newname = session_check_name(name);
|
||||||
cmdq_error(item, "bad session name: %s", newname);
|
free(name);
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (args_has(args, 'A')) {
|
if (args_has(args, 'A')) {
|
||||||
if (newname != NULL)
|
if (newname != NULL)
|
||||||
@ -126,24 +125,16 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
group = args_get(args, 't');
|
group = args_get(args, 't');
|
||||||
if (group != NULL) {
|
if (group != NULL) {
|
||||||
groupwith = target->s;
|
groupwith = target->s;
|
||||||
if (groupwith == NULL) {
|
if (groupwith == NULL)
|
||||||
if (!session_check_name(group)) {
|
|
||||||
cmdq_error(item, "bad group name: %s", group);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
sg = session_group_find(group);
|
sg = session_group_find(group);
|
||||||
} else
|
else
|
||||||
sg = session_group_contains(groupwith);
|
sg = session_group_contains(groupwith);
|
||||||
if (sg != NULL)
|
if (sg != NULL)
|
||||||
prefix = sg->name;
|
prefix = xstrdup(sg->name);
|
||||||
else if (groupwith != NULL)
|
else if (groupwith != NULL)
|
||||||
prefix = groupwith->name;
|
prefix = xstrdup(groupwith->name);
|
||||||
else
|
else
|
||||||
prefix = group;
|
prefix = session_check_name(group);
|
||||||
} else {
|
|
||||||
groupwith = NULL;
|
|
||||||
sg = NULL;
|
|
||||||
prefix = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set -d if no client. */
|
/* Set -d if no client. */
|
||||||
@ -353,10 +344,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
free(cwd);
|
free(cwd);
|
||||||
free(newname);
|
free(newname);
|
||||||
|
free(prefix);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
free(cwd);
|
free(cwd);
|
||||||
free(newname);
|
free(newname);
|
||||||
|
free(prefix);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -49,19 +49,15 @@ cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
char *newname;
|
char *newname, *tmp;
|
||||||
|
|
||||||
newname = format_single_from_target(item, args->argv[0]);
|
tmp = format_single_from_target(item, args->argv[0]);
|
||||||
|
newname = session_check_name(tmp);
|
||||||
|
free(tmp);
|
||||||
if (strcmp(newname, s->name) == 0) {
|
if (strcmp(newname, s->name) == 0) {
|
||||||
free(newname);
|
free(newname);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session_check_name(newname)) {
|
|
||||||
cmdq_error(item, "bad session name: %s", newname);
|
|
||||||
free(newname);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (session_find(newname) != NULL) {
|
if (session_find(newname) != NULL) {
|
||||||
cmdq_error(item, "duplicate session: %s", newname);
|
cmdq_error(item, "duplicate session: %s", newname);
|
||||||
free(newname);
|
free(newname);
|
||||||
|
18
session.c
18
session.c
@ -122,7 +122,6 @@ session_create(const char *prefix, const char *name, const char *cwd,
|
|||||||
|
|
||||||
s->cwd = xstrdup(cwd);
|
s->cwd = xstrdup(cwd);
|
||||||
|
|
||||||
s->curw = NULL;
|
|
||||||
TAILQ_INIT(&s->lastw);
|
TAILQ_INIT(&s->lastw);
|
||||||
RB_INIT(&s->windows);
|
RB_INIT(&s->windows);
|
||||||
|
|
||||||
@ -141,7 +140,6 @@ session_create(const char *prefix, const char *name, const char *cwd,
|
|||||||
s->name = xstrdup(name);
|
s->name = xstrdup(name);
|
||||||
s->id = next_session_id++;
|
s->id = next_session_id++;
|
||||||
} else {
|
} else {
|
||||||
s->name = NULL;
|
|
||||||
do {
|
do {
|
||||||
s->id = next_session_id++;
|
s->id = next_session_id++;
|
||||||
free(s->name);
|
free(s->name);
|
||||||
@ -231,11 +229,20 @@ session_destroy(struct session *s, int notify, const char *from)
|
|||||||
session_remove_ref(s, __func__);
|
session_remove_ref(s, __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check a session name is valid: not empty and no colons or periods. */
|
/* Sanitize session name. */
|
||||||
int
|
char *
|
||||||
session_check_name(const char *name)
|
session_check_name(const char *name)
|
||||||
{
|
{
|
||||||
return (*name != '\0' && name[strcspn(name, ":.")] == '\0');
|
char *copy, *cp, *new_name;
|
||||||
|
|
||||||
|
copy = xstrdup(name);
|
||||||
|
for (cp = copy; *cp != '\0'; cp++) {
|
||||||
|
if (*cp == ':' || *cp == '.')
|
||||||
|
*cp = '_';
|
||||||
|
}
|
||||||
|
utf8_stravis(&new_name, copy, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
|
||||||
|
free(copy);
|
||||||
|
return (new_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock session if it has timed out. */
|
/* Lock session if it has timed out. */
|
||||||
@ -555,6 +562,7 @@ session_group_remove(struct session *s)
|
|||||||
TAILQ_REMOVE(&sg->sessions, s, gentry);
|
TAILQ_REMOVE(&sg->sessions, s, gentry);
|
||||||
if (TAILQ_EMPTY(&sg->sessions)) {
|
if (TAILQ_EMPTY(&sg->sessions)) {
|
||||||
RB_REMOVE(session_groups, &session_groups, sg);
|
RB_REMOVE(session_groups, &session_groups, sg);
|
||||||
|
free((void *)sg->name);
|
||||||
free(sg);
|
free(sg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
tmux.h
2
tmux.h
@ -2722,7 +2722,7 @@ struct session *session_create(const char *, const char *, const char *,
|
|||||||
void session_destroy(struct session *, int, const char *);
|
void session_destroy(struct session *, int, const char *);
|
||||||
void session_add_ref(struct session *, const char *);
|
void session_add_ref(struct session *, const char *);
|
||||||
void session_remove_ref(struct session *, const char *);
|
void session_remove_ref(struct session *, const char *);
|
||||||
int session_check_name(const char *);
|
char *session_check_name(const char *);
|
||||||
void session_update_activity(struct session *, struct timeval *);
|
void session_update_activity(struct session *, struct timeval *);
|
||||||
struct session *session_next_session(struct session *);
|
struct session *session_next_session(struct session *);
|
||||||
struct session *session_previous_session(struct session *);
|
struct session *session_previous_session(struct session *);
|
||||||
|
Reference in New Issue
Block a user