diff --git a/common/ipc-client.c b/common/ipc-client.c index 106f9d86..d011bd26 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -52,10 +52,18 @@ struct ipc_response *ipc_recv_response(int socketfd) { } struct ipc_response *response = malloc(sizeof(struct ipc_response)); + if (!response) { + goto error_1; + } + total = 0; response->size = data32[0]; response->type = data32[1]; char *payload = malloc(response->size + 1); + if (!payload) { + goto error_2; + } + while (total < response->size) { ssize_t received = recv(socketfd, payload + total, response->size - total, 0); if (received < 0) { @@ -67,6 +75,11 @@ struct ipc_response *ipc_recv_response(int socketfd) { response->payload = payload; return response; +error_2: + free(response); +error_1: + sway_log(L_ERROR, "Unable to allocate memory for IPC response"); + return NULL; } void free_ipc_response(struct ipc_response *response) { diff --git a/common/list.c b/common/list.c index d57234e3..dd864a9b 100644 --- a/common/list.c +++ b/common/list.c @@ -5,6 +5,9 @@ list_t *create_list(void) { list_t *list = malloc(sizeof(list_t)); + if (!list) { + return NULL; + } list->capacity = 10; list->length = 0; list->items = malloc(sizeof(void*) * list->capacity); diff --git a/common/log.c b/common/log.c index 4f0baa3f..825b176b 100644 --- a/common/log.c +++ b/common/log.c @@ -88,9 +88,14 @@ void _sway_log(const char *filename, int line, log_importance_t verbosity, const } if (filename && line) { - char *file = strdup(filename); - fprintf(stderr, "[%s:%d] ", basename(file), line); - free(file); + const char *file = filename + strlen(filename); + while (file != filename && *file != '/') { + --file; + } + if (*file == '/') { + ++file; + } + fprintf(stderr, "[%s:%d] ", file, line); } va_list args; diff --git a/common/readline.c b/common/readline.c index 5106172c..cc40a2cc 100644 --- a/common/readline.c +++ b/common/readline.c @@ -1,4 +1,5 @@ #include "readline.h" +#include "log.h" #include #include @@ -7,6 +8,7 @@ char *read_line(FILE *file) { char *string = malloc(size); char lastChar = '\0'; if (!string) { + sway_log(L_ERROR, "Unable to allocate memory for read_line"); return NULL; } while (1) { @@ -27,6 +29,7 @@ char *read_line(FILE *file) { char *new_string = realloc(string, size *= 2); if (!new_string) { free(string); + sway_log(L_ERROR, "Unable to allocate memory for read_line"); return NULL; } string = new_string; diff --git a/include/log.h b/include/log.h index ca8c1fe3..2c4150e4 100644 --- a/include/log.h +++ b/include/log.h @@ -25,13 +25,8 @@ bool _sway_assert(bool condition, const char* format, ...) __attribute__((format void _sway_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) __attribute__((format(printf,4,5))); -#ifndef NDEBUG #define sway_log(VERBOSITY, FMT, ...) \ _sway_log(__FILE__, __LINE__, VERBOSITY, FMT, ##__VA_ARGS__) -#else -#define sway_log(VERBOSITY, FMT, ...) \ - _sway_log(NULL, 0, VERBOSITY, FMT, ##__VA_ARGS__) -#endif void error_handler(int sig); diff --git a/sway/border.c b/sway/border.c index c96ae6fe..5ae32d24 100644 --- a/sway/border.c +++ b/sway/border.c @@ -29,20 +29,24 @@ void border_clear(struct border *border) { static cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry g, cairo_surface_t **surface) { if (view->border == NULL) { view->border = malloc(sizeof(struct border)); + if (!view->border) { + sway_log(L_ERROR, "Unable to allocate window border information"); + return NULL; + } } cairo_t *cr; int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, g.size.w); view->border->buffer = calloc(stride * g.size.h, sizeof(unsigned char)); view->border->geometry = g; if (!view->border->buffer) { - sway_log(L_DEBUG, "Unable to allocate buffer"); + sway_log(L_ERROR, "Unable to allocate window border buffer"); return NULL; } *surface = cairo_image_surface_create_for_data(view->border->buffer, CAIRO_FORMAT_ARGB32, g.size.w, g.size.h, stride); if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) { border_clear(view->border); - sway_log(L_DEBUG, "Unable to allocate surface"); + sway_log(L_ERROR, "Unable to allocate window border surface"); return NULL; } cr = cairo_create(*surface); @@ -50,7 +54,7 @@ static cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry g, cairo if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy(*surface); border_clear(view->border); - sway_log(L_DEBUG, "Unable to create cairo context"); + sway_log(L_ERROR, "Unable to create cairo context"); return NULL; } return cr; @@ -238,6 +242,10 @@ static char *generate_container_title(swayc_t *container) { } int len = 9; name = malloc(len * sizeof(char)); + if (!name) { + sway_log(L_ERROR, "Unable to allocate container title"); + return NULL; + } snprintf(name, len, "sway: %c[", layout); int i; @@ -257,6 +265,11 @@ static char *generate_container_title(swayc_t *container) { } name = malloc(len * sizeof(char)); + if (!name) { + free(prev_name); + sway_log(L_ERROR, "Unable to allocate container title"); + return NULL; + } if (i < container->children->length-1) { snprintf(name, len, "%s%s ", prev_name, title); } else { @@ -268,6 +281,11 @@ static char *generate_container_title(swayc_t *container) { prev_name = name; len = strlen(name) + 2; name = malloc(len * sizeof(char)); + if (!name) { + free(prev_name); + sway_log(L_ERROR, "Unable to allocate container title"); + return NULL; + } snprintf(name, len, "%s]", prev_name); free(prev_name); free(container->name); @@ -347,6 +365,9 @@ static void update_view_border(swayc_t *view) { } }; cr = create_border_buffer(view, g, &surface); + if (!cr) { + goto cleanup; + } bool render_top = !should_hide_top_border(view, view->y); if (view == focused || is_child_of_focused) { @@ -408,6 +429,8 @@ static void update_view_border(swayc_t *view) { } } +cleanup: + if (surface) { cairo_surface_flush(surface); cairo_surface_destroy(surface); diff --git a/sway/commands.c b/sway/commands.c index d87d0084..c15cb00a 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -121,6 +121,9 @@ void input_cmd_apply(struct input_config *input) { for (int i = 0; i < input_devices->length; ++i) { device = input_devices->items[i]; char* dev_identifier = libinput_dev_unique_id(device); + if (!dev_identifier) { + break; + } int match = dev_identifier && strcmp(dev_identifier, input->identifier) == 0; free(dev_identifier); if (match) { @@ -386,7 +389,11 @@ struct cmd_results *handle_command(char *_exec, enum command_context context) { if (!results) { int len = strlen(criteria) + strlen(head) + 4; char *tmp = malloc(len); - snprintf(tmp, len, "[%s] %s", criteria, head); + if (tmp) { + snprintf(tmp, len, "[%s] %s", criteria, head); + } else { + sway_log(L_DEBUG, "Unable to allocate criteria string for cmd result"); + } results = cmd_results_new(CMD_INVALID, tmp, "Can't handle criteria string: Refusing to execute command"); free(tmp); @@ -568,6 +575,9 @@ struct cmd_results *config_commands_command(char *exec) { } if (!policy) { policy = alloc_command_policy(cmd); + if (!policy) { + sway_abort("Unable to allocate security policy"); + } list_add(config->command_policies, policy); } policy->context = context; @@ -584,6 +594,10 @@ cleanup: struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, const char *format, ...) { struct cmd_results *results = malloc(sizeof(struct cmd_results)); + if (!results) { + sway_log(L_ERROR, "Unable to allocate command results"); + return NULL; + } results->status = status; if (input) { results->input = strdup(input); // input is the command name @@ -594,7 +608,9 @@ struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, c char *error = malloc(256); va_list args; va_start(args, format); - vsnprintf(error, 256, format, args); + if (error) { + vsnprintf(error, 256, format, args); + } va_end(args); results->error = error; } else { diff --git a/sway/commands/assign.c b/sway/commands/assign.c index 53c599ca..992b4692 100644 --- a/sway/commands/assign.c +++ b/sway/commands/assign.c @@ -23,10 +23,16 @@ struct cmd_results *cmd_assign(int argc, char **argv) { char *movecmd = "move container to workspace "; int arglen = strlen(movecmd) + strlen(*argv) + 1; char *cmdlist = calloc(1, arglen); - + if (!cmdlist) { + return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate command list"); + } snprintf(cmdlist, arglen, "%s%s", movecmd, *argv); struct criteria *crit = malloc(sizeof(struct criteria)); + if (!crit) { + free(cmdlist); + return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate criteria"); + } crit->crit_raw = strdup(criteria); crit->cmdlist = cmdlist; crit->tokens = create_list(); diff --git a/sway/commands/bar.c b/sway/commands/bar.c index 55cb0d9d..e8d24084 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -32,6 +32,9 @@ struct cmd_results *cmd_bar(int argc, char **argv) { // Create new bar with default values struct bar_config *bar = default_bar_config(); + if (!bar) { + return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar state"); + } // set bar id int i; @@ -39,7 +42,11 @@ struct cmd_results *cmd_bar(int argc, char **argv) { if (bar == config->bars->items[i]) { const int len = 5 + numlen(i); // "bar-" + i + \0 bar->id = malloc(len * sizeof(char)); - snprintf(bar->id, len, "bar-%d", i); + if (bar->id) { + snprintf(bar->id, len, "bar-%d", i); + } else { + return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar ID"); + } break; } } diff --git a/sway/commands/bar/bindsym.c b/sway/commands/bar/bindsym.c index bb81b4a9..5f90b51a 100644 --- a/sway/commands/bar/bindsym.c +++ b/sway/commands/bar/bindsym.c @@ -26,6 +26,9 @@ struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "bindsym", "Invalid mouse binding %s", argv[1]); } struct sway_mouse_binding *binding = malloc(sizeof(struct sway_mouse_binding)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, "bindsym", "Unable to allocate binding"); + } binding->button = numbutton; binding->command = join_args(argv + 1, argc - 1); diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c index f6fb520a..8b3b0aac 100644 --- a/sway/commands/bar/colors.c +++ b/sway/commands/bar/colors.c @@ -9,6 +9,9 @@ static struct cmd_results *parse_single_color(char **color, const char *cmd_name if (!*color) { *color = malloc(10); + if (!*color) { + return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); + } } error = add_color(cmd_name, *color, argv[0]); @@ -29,6 +32,9 @@ static struct cmd_results *parse_three_colors(char ***colors, const char *cmd_na for (i = 0; i < 3; i++) { if (!*colors[i]) { *(colors[i]) = malloc(10); + if (!*(colors[i])) { + return cmd_results_new(CMD_FAILURE, cmd_name, "Unable to allocate color"); + } } error = add_color(cmd_name, *(colors[i]), argv[i]); if (error) { diff --git a/sway/commands/bind.c b/sway/commands/bind.c index e8bb3ee8..8282277b 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -16,6 +16,10 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { } struct sway_binding *binding = malloc(sizeof(struct sway_binding)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, "bindsym", + "Unable to allocate binding"); + } binding->keys = create_list(); binding->modifiers = 0; binding->release = false; @@ -46,14 +50,21 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { continue; } // Check for xkb key - xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); + xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], + XKB_KEYSYM_CASE_INSENSITIVE); if (!sym) { - error = cmd_results_new(CMD_INVALID, "bindsym", "Unknown key '%s'", (char *)split->items[i]); free_sway_binding(binding); - list_free(split); - return error; + free_flat_list(split); + return cmd_results_new(CMD_INVALID, "bindsym", "Unknown key '%s'", + (char *)split->items[i]); } xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); + if (!key) { + free_sway_binding(binding); + free_flat_list(split); + return cmd_results_new(CMD_FAILURE, "bindsym", + "Unable to allocate binding"); + } *key = sym; list_add(binding->keys, key); } @@ -82,6 +93,10 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { } struct sway_binding *binding = malloc(sizeof(struct sway_binding)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, "bindsym", + "Unable to allocate binding"); + } binding->keys = create_list(); binding->modifiers = 0; binding->release = false; diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 157d4872..1d7cd494 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -39,6 +39,9 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { pid_t pid; pid_t *child = malloc(sizeof(pid_t)); // malloc'd so that Linux can avoid copying the process space + if (!child) { + return cmd_results_new(CMD_FAILURE, "exec_always", "Unable to allocate child pid"); + } // Fork process if ((pid = fork()) == 0) { // Fork child process again @@ -56,7 +59,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { _exit(0); // Close child process } else if (pid < 0) { free(child); - return cmd_results_new(CMD_FAILURE, "exec_always", "Command failed (sway could not fork)."); + return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed"); } close(fd[1]); // close write ssize_t s = 0; @@ -73,8 +76,6 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { pw->pid = child; pw->workspace = strdup(ws->name); pid_workspace_add(pw); - // TODO: keep track of this pid and open the corresponding view on the current workspace - // blocked pending feature in wlc } else { free(child); } diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c index 2ba0ea6c..8c5722fd 100644 --- a/sway/commands/for_window.c +++ b/sway/commands/for_window.c @@ -14,6 +14,9 @@ struct cmd_results *cmd_for_window(int argc, char **argv) { char *criteria = argv[0], *cmdlist = join_args(argv + 1, argc - 1); struct criteria *crit = malloc(sizeof(struct criteria)); + if (!crit) { + return cmd_results_new(CMD_FAILURE, "for_window", "Unable to allocate criteria"); + } crit->crit_raw = strdup(criteria); crit->cmdlist = cmdlist; crit->tokens = create_list(); diff --git a/sway/commands/mode.c b/sway/commands/mode.c index f9cb271e..ed3f432f 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c @@ -30,7 +30,10 @@ struct cmd_results *cmd_mode(int argc, char **argv) { } // Create mode if it doesn't exist if (!mode && mode_make) { - mode = malloc(sizeof*mode); + mode = malloc(sizeof(struct sway_mode)); + if (!mode) { + return cmd_results_new(CMD_FAILURE, "mode", "Unable to allocate mode"); + } mode->name = strdup(mode_name); mode->bindings = create_list(); list_add(config->modes, mode); diff --git a/sway/commands/output.c b/sway/commands/output.c index 6c1c55b5..01ac9f4e 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -26,6 +26,9 @@ struct cmd_results *cmd_output(int argc, char **argv) { const char *name = argv[0]; struct output_config *output = calloc(1, sizeof(struct output_config)); + if (!output) { + return cmd_results_new(CMD_FAILURE, "output", "Unable to allocate output config"); + } output->x = output->y = output->width = output->height = -1; output->name = strdup(name); output->enabled = -1; @@ -113,12 +116,20 @@ struct cmd_results *cmd_output(int argc, char **argv) { src = p.we_wordv[0]; if (config->reading && *src != '/') { char *conf = strdup(config->current_config); - char *conf_path = dirname(conf); - src = malloc(strlen(conf_path) + strlen(src) + 2); - sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); - free(conf); + if (conf) { + char *conf_path = dirname(conf); + src = malloc(strlen(conf_path) + strlen(src) + 2); + if (src) { + sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); + } else { + sway_log(L_ERROR, "Unable to allocate background source"); + } + free(conf); + } else { + sway_log(L_ERROR, "Unable to allocate background source"); + } } - if (access(src, F_OK) == -1) { + if (!src || access(src, F_OK) == -1) { return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src); } for (char *m = mode; *m; ++m) *m = tolower(*m); diff --git a/sway/commands/permit.c b/sway/commands/permit.c index 7a25e4ce..dee246d7 100644 --- a/sway/commands/permit.c +++ b/sway/commands/permit.c @@ -50,6 +50,9 @@ static struct feature_policy *get_policy(const char *name) { } if (!policy) { policy = alloc_feature_policy(name); + if (!policy) { + sway_abort("Unable to allocate security policy"); + } list_add(config->feature_policies, policy); } return policy; diff --git a/sway/commands/set.c b/sway/commands/set.c index 1f324951..8b293825 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -47,6 +47,9 @@ struct cmd_results *cmd_set(int argc, char **argv) { free(var->value); } else { var = malloc(sizeof(struct sway_variable)); + if (!var) { + return cmd_results_new(CMD_FAILURE, "set", "Unable to allocate variable"); + } var->name = strdup(argv[0]); list_add(config->symbols, var); list_qsort(config->symbols, compare_set_qsort); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 35224f8a..14fe242f 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -61,6 +61,10 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { return error; } struct workspace_output *wso = calloc(1, sizeof(struct workspace_output)); + if (!wso) { + return cmd_results_new(CMD_FAILURE, "workspace output", + "Unable to allocate workspace output"); + } wso->workspace = strdup(argv[0]); wso->output = strdup(argv[2]); int i = -1; diff --git a/sway/config.c b/sway/config.c index e737f83c..4164cefa 100644 --- a/sway/config.c +++ b/sway/config.c @@ -29,21 +29,30 @@ struct sway_config *config = NULL; static void terminate_swaybar(pid_t pid); static void free_variable(struct sway_variable *var) { + if (!var) { + return; + } free(var->name); free(var->value); free(var); } static void free_binding(struct sway_binding *bind) { + if (!bind) { + return; + } free_flat_list(bind->keys); free(bind->command); free(bind); } static void free_mode(struct sway_mode *mode) { + if (!mode) { + return; + } free(mode->name); int i; - for (i = 0; i < mode->bindings->length; ++i) { + for (i = 0; mode->bindings && i < mode->bindings->length; ++i) { free_binding(mode->bindings->items[i]); } list_free(mode->bindings); @@ -51,13 +60,16 @@ static void free_mode(struct sway_mode *mode) { } static void free_bar(struct bar_config *bar) { + if (!bar) { + return; + } free(bar->mode); free(bar->hidden_state); free(bar->status_command); free(bar->font); free(bar->separator_symbol); int i; - for (i = 0; i < bar->bindings->length; ++i) { + for (i = 0; bar->bindings && i < bar->bindings->length; ++i) { free_sway_mouse_binding(bar->bindings->items[i]); } list_free(bar->bindings); @@ -96,16 +108,25 @@ static void free_bar(struct bar_config *bar) { } void free_input_config(struct input_config *ic) { + if (!ic) { + return; + } free(ic->identifier); free(ic); } void free_output_config(struct output_config *oc) { + if (!oc) { + return; + } free(oc->name); free(oc); } static void free_workspace_output(struct workspace_output *wo) { + if (!wo) { + return; + } free(wo->output); free(wo->workspace); free(wo); @@ -134,6 +155,10 @@ void pid_workspace_add(struct pid_workspace *pw) { struct pid_workspace *list_pw = NULL; struct timespec ts; time_t *now = malloc(sizeof(time_t)); + if (!now) { + sway_log(L_ERROR, "Allocating time for pid_workspace failed"); + return; + } pid_workspace_cleanup(); @@ -168,65 +193,74 @@ void free_pid_workspace(struct pid_workspace *pw) { } void free_command_policy(struct command_policy *policy) { + if (!policy) { + return; + } free(policy->command); free(policy); } void free_feature_policy(struct feature_policy *policy) { + if (!policy) { + return; + } free(policy->program); free(policy); } void free_config(struct sway_config *config) { + if (!config) { + return; + } int i; - for (i = 0; i < config->symbols->length; ++i) { + for (i = 0; config->symbols && i < config->symbols->length; ++i) { free_variable(config->symbols->items[i]); } list_free(config->symbols); - for (i = 0; i < config->modes->length; ++i) { + for (i = 0; config->modes && i < config->modes->length; ++i) { free_mode(config->modes->items[i]); } list_free(config->modes); - for (i = 0; i < config->bars->length; ++i) { + for (i = 0; config->bars && i < config->bars->length; ++i) { free_bar(config->bars->items[i]); } list_free(config->bars); free_flat_list(config->cmd_queue); - for (i = 0; i < config->workspace_outputs->length; ++i) { + for (i = 0; config->workspace_outputs && i < config->workspace_outputs->length; ++i) { free_workspace_output(config->workspace_outputs->items[i]); } list_free(config->workspace_outputs); - for (i = 0; i < config->pid_workspaces->length; ++i) { + for (i = 0; config->pid_workspaces && i < config->pid_workspaces->length; ++i) { free_pid_workspace(config->pid_workspaces->items[i]); } list_free(config->pid_workspaces); - for (i = 0; i < config->criteria->length; ++i) { + for (i = 0; config->criteria && i < config->criteria->length; ++i) { free_criteria(config->criteria->items[i]); } list_free(config->criteria); - for (i = 0; i < config->input_configs->length; ++i) { + for (i = 0; config->input_configs && i < config->input_configs->length; ++i) { free_input_config(config->input_configs->items[i]); } list_free(config->input_configs); - for (i = 0; i < config->output_configs->length; ++i) { + for (i = 0; config->output_configs && i < config->output_configs->length; ++i) { free_output_config(config->output_configs->items[i]); } list_free(config->output_configs); - for (i = 0; i < config->command_policies->length; ++i) { + for (i = 0; config->command_policies && i < config->command_policies->length; ++i) { free_command_policy(config->command_policies->items[i]); } list_free(config->command_policies); - for (i = 0; i < config->feature_policies->length; ++i) { + for (i = 0; config->feature_policies && i < config->feature_policies->length; ++i) { free_feature_policy(config->feature_policies->items[i]); } list_free(config->feature_policies); @@ -243,37 +277,37 @@ void free_config(struct sway_config *config) { static bool file_exists(const char *path) { - return access(path, R_OK) != -1; + return path && access(path, R_OK) != -1; } static void config_defaults(struct sway_config *config) { - config->symbols = create_list(); - config->modes = create_list(); - config->bars = create_list(); - config->workspace_outputs = create_list(); - config->pid_workspaces = create_list(); - config->criteria = create_list(); - config->input_configs = create_list(); - config->output_configs = create_list(); + if (!(config->symbols = create_list())) goto cleanup; + if (!(config->modes = create_list())) goto cleanup; + if (!(config->bars = create_list())) goto cleanup; + if (!(config->workspace_outputs = create_list())) goto cleanup; + if (!(config->pid_workspaces = create_list())) goto cleanup; + if (!(config->criteria = create_list())) goto cleanup; + if (!(config->input_configs = create_list())) goto cleanup; + if (!(config->output_configs = create_list())) goto cleanup; - config->cmd_queue = create_list(); + if (!(config->cmd_queue = create_list())) goto cleanup; - config->current_mode = malloc(sizeof(struct sway_mode)); - config->current_mode->name = malloc(sizeof("default")); + if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) goto cleanup; + if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; strcpy(config->current_mode->name, "default"); - config->current_mode->bindings = create_list(); + if (!(config->current_mode->bindings = create_list())) goto cleanup; list_add(config->modes, config->current_mode); config->floating_mod = 0; config->dragging_key = M_LEFT_CLICK; config->resizing_key = M_RIGHT_CLICK; - config->floating_scroll_up_cmd = strdup(""); - config->floating_scroll_down_cmd = strdup(""); - config->floating_scroll_left_cmd = strdup(""); - config->floating_scroll_right_cmd = strdup(""); + if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup; + if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup; + if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup; + if (!(config->floating_scroll_right_cmd = strdup(""))) goto cleanup; config->default_layout = L_NONE; config->default_orientation = L_NONE; - config->font = strdup("monospace 10"); + if (!(config->font = strdup("monospace 10"))) goto cleanup; config->font_height = get_font_text_height(config->font); // floating view @@ -297,9 +331,9 @@ static void config_defaults(struct sway_config *config) { config->gaps_inner = 0; config->gaps_outer = 0; - config->active_bar_modifiers = create_list(); + if (!(config->active_bar_modifiers = create_list())) goto cleanup; - config->config_chain = create_list(); + if (!(config->config_chain = create_list())) goto cleanup; config->current_config = NULL; // borders @@ -343,9 +377,13 @@ static void config_defaults(struct sway_config *config) { config->border_colors.background = 0xFFFFFFFF; // Security - config->command_policies = create_list(); - config->feature_policies = create_list(); + if (!(config->command_policies = create_list())) goto cleanup; + if (!(config->feature_policies = create_list())) goto cleanup; config->ipc_policy = UINT32_MAX; + + return; +cleanup: + sway_abort("Unable to allocate config structures"); } static int compare_modifiers(const void *left, const void *right) { @@ -386,11 +424,15 @@ static char *get_config_path(void) { if (!getenv("XDG_CONFIG_HOME")) { char *home = getenv("HOME"); char *config_home = malloc(strlen(home) + strlen("/.config") + 1); - strcpy(config_home, home); - strcat(config_home, "/.config"); - setenv("XDG_CONFIG_HOME", config_home, 1); - sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); - free(config_home); + if (!config_home) { + sway_log(L_ERROR, "Unable to allocate $HOME/.config"); + } else { + strcpy(config_home, home); + strcat(config_home, "/.config"); + setenv("XDG_CONFIG_HOME", config_home, 1); + sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); + free(config_home); + } } wordexp_t p; @@ -452,6 +494,9 @@ bool load_main_config(const char *file, bool is_active) { struct sway_config *old_config = config; config = calloc(1, sizeof(struct sway_config)); + if (!config) { + sway_abort("Unable to allocate config"); + } config_defaults(config); if (is_active) { @@ -491,6 +536,10 @@ static bool load_include_config(const char *path, const char *parent_dir, struct if (len >= 1 && path[0] != '/') { len = len + strlen(parent_dir) + 2; full_path = malloc(len * sizeof(char)); + if (!full_path) { + sway_log(L_ERROR, "Unable to allocate full path to included config"); + return false; + } snprintf(full_path, len, "%s/%s", parent_dir, path); } @@ -575,6 +624,9 @@ bool read_config(FILE *file, struct sway_config *config) { char *line; while (!feof(file)) { line = read_line(file); + if (!line) { + continue; + } line_number++; line = strip_whitespace(line); if (line[0] == '#') { @@ -816,6 +868,10 @@ static void invoke_swaybar(struct bar_config *bar) { // run custom swaybar int len = strlen(bar->swaybar_command) + strlen(bar->id) + 5; char *command = malloc(len * sizeof(char)); + if (!command) { + sway_log(L_ERROR, "Unable to allocate swaybar command string"); + return; + } snprintf(command, len, "%s -b %s", bar->swaybar_command, bar->id); char *const cmd[] = { @@ -1052,6 +1108,11 @@ char *do_var_replacement(char *str) { if (strncmp(find, var->name, vnlen) == 0) { int vvlen = strlen(var->value); char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); + if (!newstr) { + sway_log(L_ERROR, + "Unable to allocate replacement during variable expansion"); + break; + } char *newptr = newstr; int offset = find - str; strncpy(newptr, str, offset); @@ -1185,6 +1246,9 @@ void free_sway_mouse_binding(struct sway_mouse_binding *binding) { struct sway_binding *sway_binding_dup(struct sway_binding *sb) { struct sway_binding *new_sb = malloc(sizeof(struct sway_binding)); + if (!new_sb) { + return NULL; + } new_sb->order = sb->order; new_sb->modifiers = sb->modifiers; @@ -1194,6 +1258,10 @@ struct sway_binding *sway_binding_dup(struct sway_binding *sb) { int i; for (i = 0; i < sb->keys->length; ++i) { xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); + if (!key) { + free_sway_binding(new_sb); + return NULL; + } *key = *(xkb_keysym_t *)sb->keys->items[i]; list_add(new_sb->keys, key); } @@ -1204,13 +1272,16 @@ struct sway_binding *sway_binding_dup(struct sway_binding *sb) { struct bar_config *default_bar_config(void) { struct bar_config *bar = NULL; bar = malloc(sizeof(struct bar_config)); - bar->mode = strdup("dock"); - bar->hidden_state = strdup("hide"); + if (!bar) { + return NULL; + } + if (!(bar->mode = strdup("dock"))) goto cleanup; + if (!(bar->hidden_state = strdup("hide"))) goto cleanup; bar->modifier = WLC_BIT_MOD_LOGO; bar->outputs = NULL; bar->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; - bar->bindings = create_list(); - bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p' && sleep 1; done"); + if (!(bar->bindings = create_list())) goto cleanup; + if (!(bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p' && sleep 1; done"))) goto cleanup; bar->pango_markup = false; bar->swaybar_command = NULL; bar->font = NULL; @@ -1224,21 +1295,21 @@ struct bar_config *default_bar_config(void) { bar->verbose = false; bar->pid = 0; // set default colors - bar->colors.background = strndup("#000000ff", 9); - bar->colors.statusline = strndup("#ffffffff", 9); - bar->colors.separator = strndup("#666666ff", 9); - bar->colors.focused_workspace_border = strndup("#4c7899ff", 9); - bar->colors.focused_workspace_bg = strndup("#285577ff", 9); - bar->colors.focused_workspace_text = strndup("#ffffffff", 9); - bar->colors.active_workspace_border = strndup("#333333ff", 9); - bar->colors.active_workspace_bg = strndup("#5f676aff", 9); - bar->colors.active_workspace_text = strndup("#ffffffff", 9); - bar->colors.inactive_workspace_border = strndup("#333333ff", 9); - bar->colors.inactive_workspace_bg = strndup("#222222ff", 9); - bar->colors.inactive_workspace_text = strndup("#888888ff", 9); - bar->colors.urgent_workspace_border = strndup("#2f343aff", 9); - bar->colors.urgent_workspace_bg = strndup("#900000ff", 9); - bar->colors.urgent_workspace_text = strndup("#ffffffff", 9); + if (!(bar->colors.background = strndup("#000000ff", 9))) goto cleanup; + if (!(bar->colors.statusline = strndup("#ffffffff", 9))) goto cleanup; + if (!(bar->colors.separator = strndup("#666666ff", 9))) goto cleanup; + if (!(bar->colors.focused_workspace_border = strndup("#4c7899ff", 9))) goto cleanup; + if (!(bar->colors.focused_workspace_bg = strndup("#285577ff", 9))) goto cleanup; + if (!(bar->colors.focused_workspace_text = strndup("#ffffffff", 9))) goto cleanup; + if (!(bar->colors.active_workspace_border = strndup("#333333ff", 9))) goto cleanup; + if (!(bar->colors.active_workspace_bg = strndup("#5f676aff", 9))) goto cleanup; + if (!(bar->colors.active_workspace_text = strndup("#ffffffff", 9))) goto cleanup; + if (!(bar->colors.inactive_workspace_border = strndup("#333333ff", 9))) goto cleanup; + if (!(bar->colors.inactive_workspace_bg = strndup("#222222ff", 9))) goto cleanup; + if (!(bar->colors.inactive_workspace_text = strndup("#888888ff", 9))) goto cleanup; + if (!(bar->colors.urgent_workspace_border = strndup("#2f343aff", 9))) goto cleanup; + if (!(bar->colors.urgent_workspace_bg = strndup("#900000ff", 9))) goto cleanup; + if (!(bar->colors.urgent_workspace_text = strndup("#ffffffff", 9))) goto cleanup; // if the following colors stay undefined, they fall back to background, // statusline, separator and urgent_workspace_*. bar->colors.focused_background = NULL; @@ -1251,4 +1322,8 @@ struct bar_config *default_bar_config(void) { list_add(config->bars, bar); return bar; + +cleanup: + free_bar(bar); + return NULL; } diff --git a/sway/container.c b/sway/container.c index e5284200..d9677cdb 100644 --- a/sway/container.c +++ b/sway/container.c @@ -23,6 +23,9 @@ static swayc_t *new_swayc(enum swayc_types type) { // next id starts at 1 because 0 is assigned to root_container in layout.c static size_t next_id = 1; swayc_t *c = calloc(1, sizeof(swayc_t)); + if (!c) { + return NULL; + } c->id = next_id++; c->handle = -1; c->gaps = -1; @@ -217,7 +220,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { workspace->y = output->y; workspace->width = output->width; workspace->height = output->height; - workspace->name = strdup(name); + workspace->name = !name ? NULL : strdup(name); workspace->visible = false; workspace->floating = create_list(); diff --git a/sway/extensions.c b/sway/extensions.c index 96c7e60d..40702e28 100644 --- a/sway/extensions.c +++ b/sway/extensions.c @@ -23,6 +23,10 @@ static struct panel_config *find_or_create_panel_config(struct wl_resource *reso } sway_log(L_DEBUG, "Creating panel config for resource %p", resource); struct panel_config *config = calloc(1, sizeof(struct panel_config)); + if (!config) { + sway_log(L_ERROR, "Unable to create panel config"); + return NULL; + } list_add(desktop_shell.panels, config); config->wl_resource = resource; return config; @@ -81,6 +85,10 @@ static void set_background(struct wl_client *client, struct wl_resource *resourc } sway_log(L_DEBUG, "Setting surface %p as background for output %d", surface, (int)output); struct background_config *config = malloc(sizeof(struct background_config)); + if (!config) { + sway_log(L_ERROR, "Unable to allocate background config"); + return; + } config->client = client; config->output = output; config->surface = wlc_resource_from_wl_surface_resource(surface); diff --git a/sway/handlers.c b/sway/handlers.c index 86a976d8..3abe2fca 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -123,6 +123,11 @@ static void update_background_geometries(wlc_handle output) { static bool handle_input_created(struct libinput_device *device) { const char *identifier = libinput_dev_unique_id(device); + if (!identifier) { + sway_log(L_ERROR, "Unable to allocate unique name for input device %p", + device); + return true; + } sway_log(L_INFO, "Found input device (%s)", identifier); list_add(input_devices, device); @@ -402,6 +407,10 @@ static bool handle_view_created(wlc_handle handle) { } else { swayc_t *output = swayc_parent_by_type(focused, C_OUTPUT); wlc_handle *h = malloc(sizeof(wlc_handle)); + if (!h) { + sway_log(L_ERROR, "Unable to allocate window handle, view handler bailing out"); + return true; + } *h = handle; sway_log(L_DEBUG, "Adding unmanaged window %p to %p", h, output->unmanaged); list_add(output->unmanaged, h); @@ -571,6 +580,10 @@ static void handle_binding_command(struct sway_binding *binding) { // binding since it will be gone after the reload has completed. if (strcasecmp(binding->command, "reload") == 0) { binding_copy = sway_binding_dup(binding); + if (!binding_copy) { + sway_log(L_ERROR, "Unable to duplicate binding during reload"); + return; + } reload = true; } diff --git a/sway/input.c b/sway/input.c index acd69a6b..249d95c6 100644 --- a/sway/input.c +++ b/sway/input.c @@ -11,8 +11,16 @@ struct input_config *new_input_config(const char* identifier) { struct input_config *input = calloc(1, sizeof(struct input_config)); + if (!input) { + sway_log(L_DEBUG, "Unable to allocate input config"); + return NULL; + } sway_log(L_DEBUG, "new_input_config(%s)", identifier); - input->identifier = strdup(identifier); + if (!(input->identifier = strdup(identifier))) { + free(input); + sway_log(L_DEBUG, "Unable to allocate input config"); + return NULL; + } input->tap = INT_MIN; input->drag_lock = INT_MIN; @@ -45,6 +53,10 @@ char *libinput_dev_unique_id(struct libinput_device *device) { int len = strlen(name) + sizeof(char) * 6; char *identifier = malloc(len); + if (!identifier) { + sway_log(L_ERROR, "Unable to allocate unique input device name"); + return NULL; + } const char *fmt = "%d:%d:%s"; snprintf(identifier, len, fmt, vendor, product, name); diff --git a/sway/ipc-json.c b/sway/ipc-json.c index e65e9de3..fd17216e 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -245,6 +245,15 @@ json_object *ipc_json_get_version() { #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE char *full_version = calloc(strlen(SWAY_GIT_VERSION) + strlen(SWAY_GIT_BRANCH) + strlen(SWAY_VERSION_DATE) + 20, 1); + if (!full_version) { + json_object_object_add(version, "human_readable", + json_object_new_string("Allocating version string failed")); + // TODO: it's stupid that we allocate this in the first place + json_object_object_add(version, "major", json_object_new_int(0)); + json_object_object_add(version, "minor", json_object_new_int(0)); + json_object_object_add(version, "patch", json_object_new_int(0)); + return version; + } strcat(full_version, SWAY_GIT_VERSION); strcat(full_version, " ("); strcat(full_version, SWAY_VERSION_DATE); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index de72beca..be6e411a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -106,7 +106,7 @@ void ipc_terminate(void) { struct sockaddr_un *ipc_user_sockaddr(void) { struct sockaddr_un *ipc_sockaddr = malloc(sizeof(struct sockaddr_un)); if (ipc_sockaddr == NULL) { - sway_abort("can't malloc ipc_sockaddr"); + sway_abort("Can't allocate ipc_sockaddr"); } ipc_sockaddr->sun_family = AF_UNIX; @@ -119,7 +119,7 @@ struct sockaddr_un *ipc_user_sockaddr(void) { } if (path_size <= snprintf(ipc_sockaddr->sun_path, path_size, "%s/sway-ipc.%i.%i.sock", dir, getuid(), getpid())) { - sway_abort("socket path won't fit into ipc_sockaddr->sun_path"); + sway_abort("Socket path won't fit into ipc_sockaddr->sun_path"); } return ipc_sockaddr; @@ -148,13 +148,13 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { int client_fd = accept(ipc_socket, NULL, NULL); if (client_fd == -1) { - sway_log_errno(L_INFO, "Unable to accept IPC client connection"); + sway_log_errno(L_ERROR, "Unable to accept IPC client connection"); return 0; } int flags; if ((flags=fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { - sway_log_errno(L_INFO, "Unable to set CLOEXEC on IPC client socket"); + sway_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); close(client_fd); return 0; } @@ -171,6 +171,11 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { } struct ipc_client* client = malloc(sizeof(struct ipc_client)); + if (!client) { + sway_log(L_ERROR, "Unable to allocate ipc client"); + close(client_fd); + return 0; + } client->payload_length = 0; client->fd = client_fd; client->subscribed_events = 0; @@ -187,7 +192,7 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WLC_EVENT_ERROR) { - sway_log(L_INFO, "IPC Client socket error, removing client"); + sway_log(L_ERROR, "IPC Client socket error, removing client"); client->fd = -1; ipc_client_disconnect(client); return 0; @@ -291,6 +296,12 @@ void ipc_get_pixels(wlc_handle output) { char response_header[9]; memset(response_header, 0, sizeof(response_header)); char *data = malloc(sizeof(response_header) + size->w * size->h * 4); + if (!data) { + sway_log(L_ERROR, "Unable to allocate pixels for get_pixels"); + ipc_client_disconnect(req->client); + free(req); + continue; + } wlc_pixels_read(WLC_RGBA8888, &req->geo, &g_out, data + sizeof(response_header)); response_header[0] = 1; @@ -318,7 +329,7 @@ void ipc_client_handle_command(struct ipc_client *client) { char *buf = malloc(client->payload_length + 1); if (!buf) { - sway_log_errno(L_INFO, "Out of memory"); + sway_log_errno(L_INFO, "Unable to allocate IPC payload"); ipc_client_disconnect(client); return; } @@ -414,7 +425,11 @@ void ipc_client_handle_command(struct ipc_client *client) { struct libinput_device *device = input_devices->items[i]; char* identifier = libinput_dev_unique_id(device); json_object *device_object = json_object_new_object(); - json_object_object_add(device_object, "identifier", json_object_new_string(identifier)); + if (!identifier) { + json_object_object_add(device_object, "identifier", NULL); + } else { + json_object_object_add(device_object, "identifier", json_object_new_string(identifier)); + } json_object_array_add(inputs, device_object); free(identifier); } @@ -493,6 +508,10 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); + if (!req) { + sway_log(L_ERROR, "Unable to allocate get_pixels request"); + goto exit_cleanup; + } req->client = client; req->output = output->handle; req->geo = g; diff --git a/sway/main.c b/sway/main.c index 157c61b3..d41eb292 100644 --- a/sway/main.c +++ b/sway/main.c @@ -53,7 +53,10 @@ void detect_proprietary() { return; } while (!feof(f)) { - char *line = read_line(f); + char *line; + if (!(line = read_line(f))) { + break; + } if (strstr(line, "nvidia")) { fprintf(stderr, "\x1B[1;31mWarning: Proprietary nvidia drivers do NOT support Wayland. Use nouveau.\x1B[0m\n"); fprintf(stderr, "\x1B[1;31mYes, they STILL don't work with the newly announced wayland \"support\".\x1B[0m\n"); @@ -118,7 +121,10 @@ static void log_distro() { if (f) { sway_log(L_INFO, "Contents of %s:", paths[i]); while (!feof(f)) { - char *line = read_line(f); + char *line; + if (!(line = read_line(f))) { + break; + } if (*line) { sway_log(L_INFO, "%s", line); } @@ -136,7 +142,10 @@ static void log_kernel() { return; } while (!feof(f)) { - char *line = read_line(f); + char *line; + if (!(line = read_line(f))) { + break; + } if (*line) { sway_log(L_INFO, "%s", line); } diff --git a/sway/security.c b/sway/security.c index 9cccd62e..41a3b94b 100644 --- a/sway/security.c +++ b/sway/security.c @@ -15,14 +15,28 @@ struct feature_policy *alloc_feature_policy(const char *program) { } struct feature_policy *policy = malloc(sizeof(struct feature_policy)); + if (!policy) { + return NULL; + } policy->program = strdup(program); + if (!policy->program) { + free(policy); + return NULL; + } policy->features = default_policy; return policy; } struct command_policy *alloc_command_policy(const char *command) { struct command_policy *policy = malloc(sizeof(struct command_policy)); + if (!policy) { + return NULL; + } policy->command = strdup(command); + if (!policy->command) { + free(policy); + return NULL; + } policy->context = 0; return policy; } @@ -35,12 +49,14 @@ enum secure_feature get_feature_policy(pid_t pid) { #endif int pathlen = snprintf(NULL, 0, fmt, pid); char *path = malloc(pathlen + 1); - snprintf(path, pathlen + 1, fmt, pid); + if (path) { + snprintf(path, pathlen + 1, fmt, pid); + } static char link[2048]; uint32_t default_policy = 0; - ssize_t len = readlink(path, link, sizeof(link)); + ssize_t len = !path ? -1 : readlink(path, link, sizeof(link)); if (len < 0) { sway_log(L_INFO, "WARNING: unable to read %s for security check. Using default policy.", diff --git a/sway/workspace.c b/sway/workspace.c index 7b24d7d9..d804126b 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -121,6 +121,10 @@ char *workspace_next_name(const char *output_name) { l = 3; } char *name = malloc(l + 1); + if (!name) { + sway_log(L_ERROR, "Could not allocate workspace name"); + return NULL; + } sprintf(name, "%d", ws_num++); return name; } @@ -278,7 +282,11 @@ bool workspace_switch(swayc_t *workspace) { || (strcmp(prev_workspace_name, active_ws->name) && active_ws != workspace)) { free(prev_workspace_name); - prev_workspace_name = malloc(strlen(active_ws->name)+1); + prev_workspace_name = malloc(strlen(active_ws->name) + 1); + if (!prev_workspace_name) { + sway_log(L_ERROR, "Unable to allocate previous workspace name"); + return false; + } strcpy(prev_workspace_name, active_ws->name); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 8d2f4e9a..f2da7392 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -331,6 +331,9 @@ void ipc_bar_init(struct bar *bar, const char *bar_id) { bool handle_ipc_event(struct bar *bar) { struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); + if (!resp) { + return false; + } switch (resp->type) { case IPC_EVENT_WORKSPACE: ipc_update_workspaces(bar);