From e35da69b87a4c54deaab2d4693a94682bd3610cf Mon Sep 17 00:00:00 2001 From: Cagebreak Signing Key 1 Date: Sun, 24 May 2020 18:48:52 +0200 Subject: [PATCH] Release 1.2.1 - Fix Issue 5 in Bugs.md - Fix Issue 6 in Bugs.md - Apply clang-format - Introduce -fanalyzer analysis for gcc compilation --- Bugs.md | 22 +++++++++- README.md | 39 ++++++++++++++++- cagebreak.c | 28 ++++++++++++- config.h.in | 1 + fuzz/fuzz-parse.c | 16 ++++--- idle_inhibit_v1.c | 7 ++++ keybinding.c | 17 +++++++- man/cagebreak-config.5.md | 2 +- man/cagebreak.1.md | 2 +- meson.build | 24 ++++++++++- message.c | 22 ++++++++++ output.c | 47 ++++++++++++++------- output.h | 6 +-- parse.c | 85 +++++++++++++++++++++++++++++++------- seat.c | 1 + signatures/1.2.0.sig | Bin 0 -> 566 bytes signatures/cagebreak.sig | Bin 566 -> 566 bytes view.c | 4 +- workspace.c | 35 +++++++++++++--- workspace.h | 5 ++- xdg_shell.c | 7 ++++ 21 files changed, 310 insertions(+), 60 deletions(-) create mode 100644 signatures/1.2.0.sig diff --git a/Bugs.md b/Bugs.md index b34f4f6..7845cca 100644 --- a/Bugs.md +++ b/Bugs.md @@ -58,8 +58,8 @@ Steps to reproduce: ### Issue 4 - github issue number: #1 - Fixed: 1.1.0 + * github issue number: #1 + * Fixed: 1.1.0 This issue is code duplication in `parse.c`. @@ -79,3 +79,21 @@ PS: As a side effect, this would allow quirky statements such as `bind dbind r hsplit` which would bind the d key to binding the r key to split the output... ``` + +### Issue 5 + + * github issue number : N/A + * Fixed: 1.2.1 + +Cagebreak up to and including release 1.2.0 does not warn of irreproducibility +if a different compiler or compiler version is used. This makes cagebreak +difficult to reproduce. + +### Issue 6 + + * github issue number : N/A + * Fixed: 1.2.1 + +Our fuzzing framework up to and including release 1.2.0 does not the limit line +lengths. This can crash the fuzzing framework with a segfault due to running +out of memory. diff --git a/README.md b/README.md index 0eb113b..9e47706 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,33 @@ Nonetheless, don't be intimidated by the (slightly lengthy) release checklist or part of this file. Do what you can, open an issue and we will collaborate toward a solution. +### GCC and -fanalyzer + +Cagebreak should compile with any reasonably new gcc or clang. Consider +a gcc version of at least [10.1](https://gcc.gnu.org/gcc-10/changes.html) if +you want to get the benefit of the brand-new +[-fanalyzer](https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html) +flag. However, this new flag sometimes produces false-postives and we +selectively disable warnings for affected code segments as described below. + +Meson is configured to set `CG_HAS_FANALYZE` if `-fanalyzer` is available. +Therefore, to maintain portability, false-positive fanalyzer warnings are to be +disabled using the following syntax: + +``` +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "WARNING OPTION" +#endif +``` +and after + +``` +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif +``` + ### Branching strategy All features are to be developed on feature branches, named after the feature. @@ -83,7 +110,8 @@ git tag -v version git push --tags origin master ``` -and a log message roughly describing the features added in the commit. +and a log message roughly describing the features added in the commit is +included. In the past, our git history did not always reflect this scheme. @@ -93,6 +121,7 @@ Release checklist * [ ] Cursory testing * [ ] libfuzzer testing + * [ ] ninja -C build clang-format * [ ] Version Number * [ ] meson.build * [ ] git tag @@ -135,6 +164,9 @@ decided on this compromise to allow flexibility and security. In general we will adapt the versions to the packages available under arch linux at the time of release. +There are reproducibility issues up to and including release `1.2.0`. See +`Issue 5` in [Bugs.md](Bugs.md). + #### Reproducible Build Instructions All hashes and signatures are provided for the following build instructions. @@ -148,6 +180,11 @@ ninja -C build For every release after 1.0.5, hashes will be provided. +1.2.1 + + * sha 256: 803f7667dc4997062f9ec95afcdca0cac68c82a7cf057cef83fe1ccfee33b8bc + * sha 512: 4d6b7efea10d190a153f893123b1715f290f4b131b490f3d23f489e2dd8edbb886001282849aad9575ad2f40375bbbded59c1cb6157115fcc14dd6a2a061b103 + 1.2.0 * sha 256: b3c6135833001a0ef600ea9628cca11f4130a524ebe748929d8f7bad034f2bf0 diff --git a/cagebreak.c b/cagebreak.c index 03cd5b9..223beae 100644 --- a/cagebreak.c +++ b/cagebreak.c @@ -198,10 +198,12 @@ set_configuration(struct cg_server *server, if(parse_rc_line(server, line) != 0) { wlr_log(WLR_ERROR, "Error in config file \"%s\", line %d\n", config_file_path, line_num); + fclose(config_file); return -1; } } } + fclose(config_file); return 0; } @@ -218,6 +220,10 @@ get_config_file() { } char *config_path = malloc( (strlen(config_home_path) + strlen(addition) + 1) * sizeof(char)); + if(!config_path) { + wlr_log(WLR_ERROR, "Failed to allocate space for configuration path"); + return NULL; + } sprintf(config_path, "%s%s", config_home_path, addition); return config_path; } @@ -256,6 +262,12 @@ main(int argc, char *argv[]) { wlr_log_init(WLR_ERROR, NULL); #endif + server.modes = malloc(4 * sizeof(char *)); + if(!server.modes) { + wlr_log(WLR_ERROR, "Error allocating mode array"); + return -1; + } + /* Wayland requires XDG_RUNTIME_DIR to be set. */ if(!getenv("XDG_RUNTIME_DIR")) { wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment"); @@ -270,11 +282,15 @@ main(int argc, char *argv[]) { server.running = true; - server.modes = malloc(4 * sizeof(char *)); server.modes[0] = strdup("top"); server.modes[1] = strdup("root"); server.modes[2] = strdup("resize"); server.modes[3] = NULL; + if(server.modes[0] == NULL || server.modes[1] == NULL || + server.modes[2] == NULL) { + wlr_log(WLR_ERROR, "Error allocating default modes"); + goto end; + } server.nws = 1; server.message_timeout = 2; @@ -530,13 +546,18 @@ main(int argc, char *argv[]) { wl_display_destroy_clients(server.wl_display); end: +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-double-free" +#endif for(unsigned int i = 0; server.modes[i] != NULL; ++i) { free(server.modes[i]); } free(server.modes); struct cg_output_config *output_config, *output_config_tmp; - wl_list_for_each_safe(output_config, output_config_tmp, &server.output_config, link) { + wl_list_for_each_safe(output_config, output_config_tmp, + &server.output_config, link) { wl_list_remove(&output_config->link); free(output_config->output_name); free(output_config); @@ -559,3 +580,6 @@ main(int argc, char *argv[]) { return ret; } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif diff --git a/config.h.in b/config.h.in index cf6bcbc..8495284 100644 --- a/config.h.in +++ b/config.h.in @@ -2,6 +2,7 @@ #define CG_CONFIG_H #mesondefine CG_HAS_XWAYLAND +#mesondefine CG_HAS_FANALYZE #mesondefine CG_VERSION diff --git a/fuzz/fuzz-parse.c b/fuzz/fuzz-parse.c index 2103a20..2434feb 100644 --- a/fuzz/fuzz-parse.c +++ b/fuzz/fuzz-parse.c @@ -8,12 +8,11 @@ #define _POSIX_C_SOURCE 200812L - #include "../keybinding.h" +#include "../output.h" #include "../parse.h" #include "../seat.h" #include "../server.h" -#include "../output.h" #include #include #include @@ -417,9 +416,13 @@ set_configuration(struct cg_server *server, char *content) { int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - char *str = malloc(size * sizeof(char) + 1); - strncpy(str, (char *)data, size); - str[size] = 0; + if(size == 0) { + return 0; + } + int max_line_size = 256 > size ? size : 256; + char *str = malloc(sizeof(char) * max_line_size); + strncpy(str, (char *)data, max_line_size); + str[max_line_size - 1] = 0; set_configuration(&server, str); free(str); keybinding_list_free(server.keybindings); @@ -450,7 +453,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { server.modes = realloc(server.modes, 4 * sizeof(char *)); struct cg_output_config *output_config, *output_config_tmp; - wl_list_for_each_safe(output_config, output_config_tmp, &server.output_config, link) { + wl_list_for_each_safe(output_config, output_config_tmp, + &server.output_config, link) { wl_list_remove(&output_config->link); free(output_config->output_name); free(output_config); diff --git a/idle_inhibit_v1.c b/idle_inhibit_v1.c index ee7ca82..17c0041 100644 --- a/idle_inhibit_v1.c +++ b/idle_inhibit_v1.c @@ -22,6 +22,10 @@ struct cg_idle_inhibitor_v1 { struct wl_listener destroy; }; +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#endif static void idle_inhibit_v1_check_active(struct cg_server *server) { /* As of right now, this does not check whether the inhibitor @@ -29,6 +33,9 @@ idle_inhibit_v1_check_active(struct cg_server *server) { bool inhibited = !wl_list_empty(&server->inhibitors); wlr_idle_set_enabled(server->idle, NULL, !inhibited); } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif static void handle_destroy(struct wl_listener *listener, void *data) { diff --git a/keybinding.c b/keybinding.c index f6f5eaf..752a434 100644 --- a/keybinding.c +++ b/keybinding.c @@ -453,8 +453,12 @@ keybinding_workspace_fullscreen(struct cg_server *server) { } workspace_free_tiles(output->workspaces[output->curr_workspace]); - full_screen_workspace_tiles(output, - output->workspaces[output->curr_workspace]); + if(full_screen_workspace_tiles( + server->output_layout, output->wlr_output, + output->workspaces[output->curr_workspace]) != 0) { + wlr_log(WLR_ERROR, "Failed to allocate space for fullscreen workspace"); + return; + } seat_set_focus(server->seat, current_view); } @@ -517,6 +521,10 @@ keybinding_split_output(struct cg_output *output, bool vertical) { } struct cg_tile *new_tile = calloc(1, sizeof(struct cg_tile)); + if(!new_tile) { + wlr_log(WLR_ERROR, "Failed to allocate new tile for splitting"); + return; + } new_tile->tile.x = new_x; new_tile->tile.y = new_y; new_tile->tile.width = x + width - new_x; @@ -741,6 +749,11 @@ keybinding_set_nws(struct cg_server *server, int nws) { output->workspaces = new_workspaces; for(int i = server->nws; i < nws; ++i) { output->workspaces[i] = full_screen_workspace(output); + if(!output->workspaces[i]) { + wlr_log(WLR_ERROR, "Failed to allocate additional workspaces"); + return; + } + wl_list_init(&output->workspaces[i]->views); wl_list_init(&output->workspaces[i]->unmanaged_views); } diff --git a/man/cagebreak-config.5.md b/man/cagebreak-config.5.md index 8f9cb72..ed82205 100644 --- a/man/cagebreak-config.5.md +++ b/man/cagebreak-config.5.md @@ -1,4 +1,4 @@ -% CAGEBREAK-CONFIG(1) Version 1.2 | Cagebreak Manual +% CAGEBREAK-CONFIG(1) Version 1.2.1 | Cagebreak Manual # NAME diff --git a/man/cagebreak.1.md b/man/cagebreak.1.md index 07c0058..a2731d3 100644 --- a/man/cagebreak.1.md +++ b/man/cagebreak.1.md @@ -1,4 +1,4 @@ -% CAGEBREAK(1) Version 1.2 | Cagebreak Manual +% CAGEBREAK(1) Version 1.2.1 | Cagebreak Manual # NAME diff --git a/meson.build b/meson.build index 40c09d7..4c8643b 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('cagebreak', 'c', - version: '1.2.0', + version: '1.2.1', license: 'MIT', default_options: [ 'c_std=c11', @@ -100,6 +100,14 @@ else have_xwayland = false endif +fanalyzer_compile_flag=[] +if cc.has_argument('-fanalyzer') + have_fanalyze=true + fanalyzer_compile_flag=[ '-fanalyzer' ] +else + have_fanalyze=false +endif + if get_option('version_override') != '' version = '@0@'.format(get_option('version_override')) else @@ -108,6 +116,7 @@ endif conf_data = configuration_data() conf_data.set10('CG_HAS_XWAYLAND', have_xwayland) +conf_data.set10('CG_HAS_FANALYZE', have_fanalyze) conf_data.set_quoted('CG_VERSION', version) @@ -208,12 +217,23 @@ foreach name, dep : cagebreak_dependencies_dict endif endforeach +reproducible_build_compiler = 'gcc' +reproducible_build_compiler_version = '10.1.0' + +if cc.get_id() != reproducible_build_compiler + warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in the README section "Reproducible Builds" (' + reproducible_build_compiler + ').') +endif + +if cc.version() != reproducible_build_compiler_version + warning('The version of ' + cc.get_id() + ' (' + cc.version() + ') differs from the one used to generate the binary specified in the README section "Reproducible Builds" ' + reproducible_build_compiler_version + '.') +endif + executable( meson.project_name(), cagebreak_main_file + cagebreak_sources + cagebreak_headers, dependencies: cagebreak_dependencies, install: true, - link_args: fuzz_link_args, + link_args: fuzz_link_args+fanalyzer_compile_flag, c_args: fuzz_compile_args, ) diff --git a/message.c b/message.c index 40ac033..8ada1f8 100644 --- a/message.c +++ b/message.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "cairo.h" #include "message.h" @@ -94,10 +95,19 @@ create_message_texture(const char *string, const struct cg_output *output) { return texture; } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#endif void message_set_output(struct cg_output *output, const char *string, struct wlr_box *box, enum cg_message_align align) { struct cg_message *message = malloc(sizeof(struct cg_message)); + if(!message) { + wlr_log(WLR_ERROR, "Error allocating message structure"); + free(box); + return; + } message->message = create_message_texture(string, output); message->position = box; wl_list_insert(&output->messages, &message->link); @@ -136,6 +146,10 @@ void message_printf(struct cg_output *output, const char *fmt, ...) { uint16_t buf_len = 256; char *buffer = (char *)malloc(buf_len * sizeof(char)); + if(buffer == NULL) { + wlr_log(WLR_ERROR, "Failed to allocate buffer in message_printf"); + return; + } va_list ap; va_start(ap, fmt); @@ -143,6 +157,11 @@ message_printf(struct cg_output *output, const char *fmt, ...) { va_end(ap); struct wlr_box *box = malloc(sizeof(struct wlr_box)); + if(box == NULL) { + wlr_log(WLR_ERROR, "Failed to allocate box in message_printf"); + free(buffer); + return; + } struct wlr_box *output_box = wlr_output_layout_get_box( output->server->output_layout, output->wlr_output); @@ -155,6 +174,9 @@ message_printf(struct cg_output *output, const char *fmt, ...) { free(buffer); alarm(output->server->message_timeout); } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif void message_printf_pos(struct cg_output *output, struct wlr_box *position, diff --git a/output.c b/output.c index 7983983..4f40050 100644 --- a/output.c +++ b/output.c @@ -480,8 +480,8 @@ handle_output_destroy(struct wl_listener *listener, void *data) { output_destroy(output); } -struct cg_output_config* -output_find_config(struct cg_server* server, struct wlr_output* output) { +struct cg_output_config * +output_find_config(struct cg_server *server, struct wlr_output *output) { struct cg_output_config *config; wl_list_for_each(config, &server->output_config, link) { if(strcmp(config->output_name, output->name) == 0) { @@ -491,31 +491,33 @@ output_find_config(struct cg_server* server, struct wlr_output* output) { return NULL; } -static void output_set_mode(struct wlr_output *output, int width, int height, - float refresh_rate) { +static void +output_set_mode(struct wlr_output *output, int width, int height, + float refresh_rate) { int mhz = (int)(refresh_rate * 1000); - if (wl_list_empty(&output->modes)) { + if(wl_list_empty(&output->modes)) { wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); wlr_output_set_custom_mode(output, width, height, - refresh_rate > 0 ? mhz : 0); + refresh_rate > 0 ? mhz : 0); return; } struct wlr_output_mode *mode, *best = NULL; wl_list_for_each(mode, &output->modes, link) { - if (mode->width == width && mode->height == height) { - if (mode->refresh == mhz) { + if(mode->width == width && mode->height == height) { + if(mode->refresh == mhz) { best = mode; break; } - if (best == NULL || mode->refresh > best->refresh) { + if(best == NULL || mode->refresh > best->refresh) { best = mode; } } } - if (!best) { - wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name); + if(!best) { + wlr_log(WLR_ERROR, "Configured mode for %s not available", + output->name); wlr_log(WLR_INFO, "Picking preferred mode instead"); best = wlr_output_preferred_mode(output); } else { @@ -525,7 +527,7 @@ static void output_set_mode(struct wlr_output *output, int width, int height, } void -output_configure(struct cg_server* server, struct cg_output *output) { +output_configure(struct cg_server *server, struct cg_output *output) { struct wlr_output *wlr_output = output->wlr_output; struct cg_output_config *config = output_find_config(server, wlr_output); if(output->wlr_output->enabled) { @@ -541,11 +543,17 @@ output_configure(struct cg_server* server, struct cg_output *output) { wlr_output_set_mode(wlr_output, preferred_mode); } } else { - output_set_mode(wlr_output, config->pos.width, config->pos.height, config->refresh_rate); - wlr_output_layout_add(server->output_layout, wlr_output, config->pos.x, config->pos.y); + output_set_mode(wlr_output, config->pos.width, config->pos.height, + config->refresh_rate); + wlr_output_layout_add(server->output_layout, wlr_output, config->pos.x, + config->pos.y); } } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#endif void handle_new_output(struct wl_listener *listener, void *data) { struct cg_server *server = wl_container_of(listener, server, new_output); @@ -580,6 +588,10 @@ handle_new_output(struct wl_listener *listener, void *data) { output->workspaces = malloc(server->nws * sizeof(struct cg_workspace *)); for(unsigned int i = 0; i < server->nws; ++i) { output->workspaces[i] = full_screen_workspace(output); + if(!output->workspaces[i]) { + wlr_log(WLR_ERROR, "Failed to allocate workspaces for output"); + return; + } wl_list_init(&output->workspaces[i]->views); wl_list_init(&output->workspaces[i]->unmanaged_views); } @@ -603,6 +615,10 @@ handle_new_output(struct wl_listener *listener, void *data) { for(unsigned int i = 0; i < server->nws; ++i) { workspace_free(output->workspaces[i]); output->workspaces[i] = full_screen_workspace(output); + if(!output->workspaces[i]) { + wlr_log(WLR_ERROR, "Failed to allocate workspaces for output"); + return; + } wl_list_init(&output->workspaces[i]->views); wl_list_init(&output->workspaces[i]->unmanaged_views); } @@ -615,6 +631,9 @@ handle_new_output(struct wl_listener *listener, void *data) { DEFAULT_XCURSOR, server->seat->cursor); wlr_cursor_warp(server->seat->cursor, NULL, 0, 0); } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif void output_set_window_title(struct cg_output *output, const char *title) { diff --git a/output.h b/output.h index ba12ea6..bf9abb4 100644 --- a/output.h +++ b/output.h @@ -29,9 +29,9 @@ struct cg_output { struct cg_output_config { struct wlr_box pos; - char* output_name; + char *output_name; float refresh_rate; - struct wl_list link;// cg_server::output_config + struct wl_list link; // cg_server::output_config }; typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, @@ -42,7 +42,7 @@ typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, void handle_new_output(struct wl_listener *listener, void *data); void -output_configure(struct cg_server* server, struct cg_output* output); +output_configure(struct cg_server *server, struct cg_output *output); void output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface, double ox, diff --git a/parse.c b/parse.c index dae5164..82cc0f2 100644 --- a/parse.c +++ b/parse.c @@ -1,9 +1,9 @@ #define _POSIX_C_SOURCE 200812L +#include #include #include #include -#include #include "keybinding.h" #include "output.h" @@ -67,6 +67,11 @@ parse_command(struct cg_server *server, struct keybinding *keybinding, struct keybinding * parse_keybinding(struct cg_server *server, char **saveptr) { struct keybinding *keybinding = malloc(sizeof(struct keybinding)); + if(keybinding == NULL) { + wlr_log(WLR_ERROR, + "Failed to allocate memory for keybinding in parse_keybinding"); + return NULL; + } char *key = strtok_r(NULL, " ", saveptr); if(parse_key(keybinding, key) != 0) { wlr_log(WLR_ERROR, "Could not parse key definition \"%s\"", key); @@ -153,6 +158,11 @@ parse_background(struct cg_server *server, float *color, char **saveptr) { struct keybinding * parse_escape(char **saveptr) { struct keybinding *keybinding = malloc(sizeof(struct keybinding)); + if(keybinding == NULL) { + wlr_log(WLR_ERROR, + "Failed to allocate memory for keybinding in parse_escape"); + return NULL; + } char *key = strtok_r(NULL, " ", saveptr); if(parse_key(keybinding, key) != 0) { wlr_log(WLR_ERROR, @@ -194,7 +204,7 @@ parse_workspaces(char **saveptr) { } int -parse_uint(char **saveptr, const char* delim) { +parse_uint(char **saveptr, const char *delim) { char *uint_str = strtok_r(NULL, delim, saveptr); if(uint_str == NULL) { wlr_log(WLR_ERROR, "Expected a non-negative integer, got nothing"); @@ -204,13 +214,16 @@ parse_uint(char **saveptr, const char* delim) { if(uint >= 0 && uint <= INT_MAX) { return uint; } else { - wlr_log(WLR_ERROR, "Error parsing non-negative integer. Must be a number larger or equal to 0 and less or equal to %d",INT_MAX); + wlr_log(WLR_ERROR, + "Error parsing non-negative integer. Must be a number larger " + "or equal to 0 and less or equal to %d", + INT_MAX); return -1; } } float -parse_float(char **saveptr, const char* delim) { +parse_float(char **saveptr, const char *delim) { char *uint_str = strtok_r(NULL, delim, saveptr); if(uint_str == NULL) { wlr_log(WLR_ERROR, "Expected a non-negative float, got nothing"); @@ -220,74 +233,114 @@ parse_float(char **saveptr, const char* delim) { if(ufloat >= 0) { return ufloat; } else { - wlr_log(WLR_ERROR, "Error parsing non-negative float. Must be a number larger or equal to 0"); + wlr_log(WLR_ERROR, "Error parsing non-negative float. Must be a number " + "larger or equal to 0"); return -1; } } int parse_output_config(struct wl_list *config_list, char **saveptr) { - struct cg_output_config* cfg = malloc(sizeof(struct cg_output_config)); + struct cg_output_config *cfg = malloc(sizeof(struct cg_output_config)); + if(cfg == NULL) { + wlr_log(WLR_ERROR, + "Failed to allocate memory for output configuration"); + goto error; + } char *name = strtok_r(NULL, " ", saveptr); if(name == NULL) { - wlr_log(WLR_ERROR, "Expected name of output to be configured, got none"); + wlr_log(WLR_ERROR, + "Expected name of output to be configured, got none"); goto error; } char *pos_str = strtok_r(NULL, " ", saveptr); if(pos_str == NULL || strcmp(pos_str, "pos") != 0) { - wlr_log(WLR_ERROR, "Expected keyword \"pos\" in output configuration for output %s", name); + wlr_log( + WLR_ERROR, + "Expected keyword \"pos\" in output configuration for output %s", + name); goto error; } cfg->pos.x = parse_uint(saveptr, " "); if(cfg->pos.x < 0) { - wlr_log(WLR_ERROR, "Error parsing x coordinate of output configuration for output %s", name); + wlr_log( + WLR_ERROR, + "Error parsing x coordinate of output configuration for output %s", + name); goto error; } cfg->pos.y = parse_uint(saveptr, " "); if(cfg->pos.y < 0) { - wlr_log(WLR_ERROR, "Error parsing y coordinate of output configuration for output %s", name); + wlr_log( + WLR_ERROR, + "Error parsing y coordinate of output configuration for output %s", + name); goto error; } char *res_str = strtok_r(NULL, " ", saveptr); if(res_str == NULL || strcmp(res_str, "res") != 0) { - wlr_log(WLR_ERROR, "Expected keyword \"res\" in output configuration for output %s", name); + wlr_log( + WLR_ERROR, + "Expected keyword \"res\" in output configuration for output %s", + name); goto error; } cfg->pos.width = parse_uint(saveptr, "x"); if(cfg->pos.width <= 0) { - wlr_log(WLR_ERROR, "Error parsing width of output configuration for output %s (hint: width must be larger than 0)", name); + wlr_log(WLR_ERROR, + "Error parsing width of output configuration for output %s " + "(hint: width must be larger than 0)", + name); goto error; } cfg->pos.height = parse_uint(saveptr, " "); if(cfg->pos.height <= 0) { - wlr_log(WLR_ERROR, "Error parsing height of output configuration for output %s (hint: height must e larger than 0)", name); + wlr_log(WLR_ERROR, + "Error parsing height of output configuration for output %s " + "(hint: height must e larger than 0)", + name); goto error; } char *rate_str = strtok_r(NULL, " ", saveptr); if(rate_str == NULL || strcmp(rate_str, "rate") != 0) { - wlr_log(WLR_ERROR, "Expected keyword \"rate\" in output configuration for output %s", name); + wlr_log( + WLR_ERROR, + "Expected keyword \"rate\" in output configuration for output %s", + name); goto error; } cfg->refresh_rate = parse_float(saveptr, " "); if(cfg->refresh_rate <= 0.0) { - wlr_log(WLR_ERROR, "Error parsing refresh rate of output configuration for output %s", name); + wlr_log( + WLR_ERROR, + "Error parsing refresh rate of output configuration for output %s", + name); goto error; } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#endif cfg->output_name = strdup(name); wl_list_insert(config_list, &cfg->link); return 0; +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif error: free(cfg); - wlr_log(WLR_ERROR, "Output configuration must be of the form \"output pos res x rate "); + wlr_log(WLR_ERROR, + "Output configuration must be of the form \"output pos " + " res x rate "); return -1; } diff --git a/seat.c b/seat.c index 7567586..ae8e52f 100644 --- a/seat.c +++ b/seat.c @@ -794,6 +794,7 @@ handle_destroy(struct wl_listener *listener, void *_data) { struct cg_keyboard_group *group, *group_tmp; wl_list_for_each_safe(group, group_tmp, &seat->keyboard_groups, link) { + wl_list_remove(&group->link); wlr_keyboard_group_destroy(group->wlr_group); wl_event_source_remove(group->key_repeat_timer); free(group); diff --git a/signatures/1.2.0.sig b/signatures/1.2.0.sig new file mode 100644 index 0000000000000000000000000000000000000000..18255c989a5f248014471ca87d0e34d33d1565fb GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j-ZpKYEIH7WG5|K!!g`E=I|>?~Ua0$#mZGyn<-5XAX( z*9`0|Td=GU0IR~cjMr-vzp4+Q%y>;=&|eqh+5NTd^Vmn-Yf;hi9?v`un2@!jWj@pD7oQnvI3QO^SRPx;FLXS9Rlm>Dx)u zj8~KZ>RgVL!w5-k+d5g)=W*(E=8ymb)fV1X|H&l<#MXRaN{|lJwd zd6Zn{<)up~7&k3dB*#A0=>Tk*iOZLIMt~y zFR_Ir{^)C8U08LeU6zITA1u^p-y14+)m+CI!*eP`gncOXgP4|!1mZ<5lNnU~kZ*p4 E?97)K8~^|S literal 0 HcmV?d00001 diff --git a/signatures/cagebreak.sig b/signatures/cagebreak.sig index 18255c989a5f248014471ca87d0e34d33d1565fb..a37d71e32647647a7bb002a6190182802402fd72 100644 GIT binary patch delta 542 zcmV+(0^$9(1hxc_BY(=Gx&R6Z5XAX(*9`0|TOcnG0FlIP=RBx_{a+33HaD1>)MaI`0crcBBFt0RJ5mVd|$aT!!ycLAjp6G_vT)Dj*E6CmG@w12!N6`*#-BR(+P8Ku=O zpP_EmJ16aa@##xv=$M`QU(IrV2|+ecF!C0AB8-W4f|}6Kn`*0s#z2`aWN_sq&$*D= zAy0s_iW1%wV#{0WCIBxSmUm-MFF++2XdBq{uFRHd6b+wtGZ+B{(hhk`0B5XX}vcMHnp5tHFArxrbtI_bet&1)c`d^>U6{Urcfn znNlE2PNzIknI~H(O7F+vvi#z}h*i~Gus`USQ7_yKw110s+l#iIzNLSlH5m=HkBmFq z%mvfmJ5K_fiEzK>0{3(7P$QfWQUo&lY74TGXZpU(Rm=IyN{&A92fzR4fSrjtJ;G9T_7bX9&#v?qpmM$ gL#YvZY!@CXqi%JK8<7W@8be!l_nW9?uxjX=MbQ2HJ^%m! delta 542 zcmV+(0^$9(1hxc_BY(YGGyn<-5XAX(*9`0|Td=GU0IR~cjMr-vzp4+Q%y>;=&|eqh z+5NTd^Vmn-Yf;hi9?v`un2@!jWj@ zpD7oQnvI3QO^SRPx;FLXS9Rlm>Dx)uj8~KZ>RgVL!w5-k+kZM))aP;Pbmou%1JxGZ zR{zN*1;o~TVdW3#Uhb`Q;<~fz(B5R11P_n7GbgxufMMH|;&cYcrf0+lhUl*@Sn_Z7 zO^Hac&@>)&^p^SdC0LWmvXnu%7haaK-Fv!OoG4^HWi=?$-!mjgX1lla;a$<^S$QFa zrqH=c&T|}&y?;NqT;}DaOMfUBH!W2p>k75}i_PWNVG8!F z49YIZ#D`M?vELRP?_B3u2=nW$b!Y_giac^m@a9zxO_FsRRuDV~RxC_}!#stghbW|4 zj`6TbAd4Q@>kHq)$ diff --git a/view.c b/view.c index 6b0ed87..609b01e 100644 --- a/view.c +++ b/view.c @@ -229,9 +229,9 @@ view_unmap(struct cg_view *view) { if((view->type != CG_XWAYLAND_VIEW || xwayland_view_should_manage(view))) #endif { - if(view_is_visible(view)) { + struct cg_tile *view_tile = view_get_tile(view); + if(view_tile != NULL) { struct cg_view *prev = view_get_prev_view(view); - struct cg_tile *view_tile = view_get_tile(view); wlr_output_damage_add_box(view_tile->workspace->output->damage, &view_tile->tile); if((view->workspace->server->seat->seat->keyboard_state diff --git a/workspace.c b/workspace.c index 8ed010e..fcc7650 100644 --- a/workspace.c +++ b/workspace.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "message.h" #include "output.h" @@ -19,27 +20,45 @@ #include "view.h" #include "workspace.h" -void -full_screen_workspace_tiles(const struct cg_output *output, +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#endif +int +full_screen_workspace_tiles(struct wlr_output_layout *layout, + struct wlr_output *output, struct cg_workspace *workspace) { - workspace->server = output->server; workspace->focused_tile = calloc(1, sizeof(struct cg_tile)); + if(!workspace->focused_tile) { + return -1; + } workspace->focused_tile->workspace = workspace; workspace->focused_tile->next = workspace->focused_tile; workspace->focused_tile->prev = workspace->focused_tile; workspace->focused_tile->tile.x = 0; workspace->focused_tile->tile.y = 0; - struct wlr_box *output_box = wlr_output_layout_get_box( - output->server->output_layout, output->wlr_output); + struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); workspace->focused_tile->tile.width = output_box->width; workspace->focused_tile->tile.height = output_box->height; workspace->focused_tile->view = NULL; + return 0; } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif struct cg_workspace * full_screen_workspace(struct cg_output *output) { struct cg_workspace *workspace = calloc(1, sizeof(struct cg_workspace)); - full_screen_workspace_tiles(output, workspace); + if(!workspace) { + return NULL; + } + workspace->server = output->server; + if(full_screen_workspace_tiles(output->server->output_layout, + output->wlr_output, workspace) != 0) { + free(workspace); + return NULL; + } workspace->output = output; return workspace; } @@ -48,6 +67,10 @@ void workspace_focus_tile(struct cg_workspace *ws, struct cg_tile *tile) { ws->focused_tile = tile; struct wlr_box *box = malloc(sizeof(struct wlr_box)); + if(!box) { + wlr_log(WLR_ERROR, "Failed to allocate box required to focus tile"); + return; + } box->x = tile->tile.x + tile->tile.width / 2; box->y = tile->tile.y + tile->tile.height / 2; message_printf_pos(ws->output, box, CG_MESSAGE_CENTER, "Current frame"); diff --git a/workspace.h b/workspace.h index 069d036..a5da674 100644 --- a/workspace.h +++ b/workspace.h @@ -25,8 +25,9 @@ struct cg_workspace { struct cg_workspace * full_screen_workspace(struct cg_output *output); -void -full_screen_workspace_tiles(const struct cg_output *output, +int +full_screen_workspace_tiles(struct wlr_output_layout *layout, + struct wlr_output *output, struct cg_workspace *workspace); void workspace_free_tiles(struct cg_workspace *workspace); diff --git a/xdg_shell.c b/xdg_shell.c index b420795..fd9ef3d 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -32,6 +32,10 @@ xdg_decoration_handle_destroy(struct wl_listener *listener, void *_data) { free(xdg_decoration); } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#endif static void xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) { struct cg_xdg_decoration *xdg_decoration = @@ -42,6 +46,9 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) { wlr_xdg_toplevel_decoration_v1_set_mode(xdg_decoration->wlr_decoration, mode); } +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif static void xdg_popup_destroy(struct cg_view_child *child) {