diff --git a/fuzz/fuzz-lib.c b/fuzz/fuzz-lib.c index c94dd8b..e46bf5d 100644 --- a/fuzz/fuzz-lib.c +++ b/fuzz/fuzz-lib.c @@ -20,8 +20,12 @@ #include #include +#include +#include +#include #include #include +#include #include #include #include @@ -88,15 +92,6 @@ drop_permissions(void) { return true; } -static bool -parse_args(struct cg_server *server, int argc, char *argv[]) { - server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL; -#ifdef DEBUG - server->debug_damage_tracking = false; -#endif - return true; -} - void cleanup() { server.running = false; @@ -120,13 +115,11 @@ cleanup() { seat_destroy(server.seat); /* This function is not null-safe, but we only ever get here with a proper wl_display. */ - wl_display_destroy(server.wl_display); wlr_output_layout_destroy(server.output_layout); } int LLVMFuzzerInitialize(int *argc, char ***argv) { - struct wl_event_loop *event_loop = NULL; struct wlr_backend *backend = NULL; struct wlr_compositor *compositor = NULL; struct wlr_data_device_manager *data_device_manager = NULL; @@ -135,13 +128,22 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL; struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; struct wlr_data_control_manager_v1 *data_control_manager = NULL; + struct wlr_viewporter *viewporter = NULL; + struct wlr_presentation *presentation = NULL; struct wlr_xdg_output_manager_v1 *output_manager = NULL; struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL; - int ret = 0; + struct wlr_xdg_shell *xdg_shell = NULL; +#if CG_HAS_XWAYLAND + struct wlr_xwayland *xwayland = NULL; +#endif + wl_list_init(&server.input_config); + wl_list_init(&server.output_config); + wl_list_init(&server.output_priorities); + wl_list_init(&server.outputs); + wl_list_init(&server.disabled_outputs); - if(!parse_args(&server, *argc, *argv)) { - return 1; - } + + int ret = 0; #ifdef DEBUG wlr_log_init(WLR_DEBUG, NULL); @@ -149,33 +151,63 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { wlr_log_init(WLR_ERROR, NULL); #endif - wl_list_init(&server.input_config); + server.modes = malloc(4 * sizeof(char *)); + if(!server.modes) { + wlr_log(WLR_ERROR, "Error allocating mode array"); + goto end; + } /* 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"); - return 1; + wlr_log(WLR_INFO, "XDG_RUNTIME_DIR is not set in the environment"); } server.wl_display = wl_display_create(); if(!server.wl_display) { wlr_log(WLR_ERROR, "Cannot allocate a Wayland display"); - return 1; + free(server.modes); + server.modes=NULL; + goto end; + } + + server.xcursor_size=XCURSOR_SIZE; + const char *env_cursor_size = getenv("XCURSOR_SIZE"); + if (env_cursor_size && strlen(env_cursor_size) > 0) { + errno = 0; + char *end; + unsigned size = strtoul(env_cursor_size, &end, 10); + if (!*end && errno == 0) { + server.xcursor_size = size; + } } 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; + server.views_curr_id = 1; + server.tiles_curr_id = 1; + server.message_config.fg_color[0] = 0.0; + server.message_config.fg_color[1] = 0.0; + server.message_config.fg_color[2] = 0.0; + server.message_config.fg_color[3] = 1.0; - event_loop = wl_display_get_event_loop(server.wl_display); - server.event_loop = event_loop; + server.message_config.bg_color[0] = 0.9; + server.message_config.bg_color[1] = 0.85; + server.message_config.bg_color[2] = 0.85; + server.message_config.bg_color[3] = 1.0; + + server.message_config.display_time = 2; + server.message_config.font = strdup("pango:Monospace 10"); backend = wlr_multi_backend_create(server.wl_display); if(!backend) { @@ -201,10 +233,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { goto end; }; - if(!drop_permissions()) { - ret = 1; - goto end; - } server.keybindings = keybinding_list_init(); if(server.keybindings == NULL || server.keybindings->keybindings == NULL) { @@ -213,14 +241,13 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { goto end; } - wl_list_init(&server.output_config); - server.renderer = wlr_renderer_autocreate(backend); if(!server.renderer) { wlr_log(WLR_ERROR, "Unable to create the wlroots renderer"); ret = 1; goto end; } + server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); if(!server.allocator) { @@ -228,16 +255,10 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { ret = 1; goto end; } + wlr_renderer_init_wl_display(server.renderer, server.wl_display); - server.bg_color = malloc(4 * sizeof(float)); - server.bg_color[0] = 0; - server.bg_color[1] = 0; - server.bg_color[2] = 0; - server.bg_color[3] = 1; - wl_list_init(&server.outputs); - wl_list_init(&server.disabled_outputs); - + server.bg_color = (float[4]){0, 0, 0, 1}; server.output_layout = wlr_output_layout_create(); if(!server.output_layout) { wlr_log(WLR_ERROR, "Unable to create output layout"); @@ -245,6 +266,27 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { goto end; } + if(ipc_init(&server) != 0) { + wlr_log(WLR_ERROR, "Failed to initialize IPC"); + ret = 1; + goto end; + } + + server.scene = wlr_scene_create(); + if(!server.scene) { + wlr_log(WLR_ERROR, "Unable to create scene"); + ret = 1; + goto end; + } + wlr_scene_attach_output_layout(server.scene, server.output_layout); + + compositor = wlr_compositor_create(server.wl_display, server.renderer); + if(!compositor) { + wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); + ret = 1; + goto end; + } + data_device_manager = wlr_data_device_manager_create(server.wl_display); if(!data_device_manager) { wlr_log(WLR_ERROR, "Unable to create the data device manager"); @@ -324,6 +366,21 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { wlr_server_decoration_manager_set_default_mode( server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + viewporter = wlr_viewporter_create(server.wl_display); + if(!viewporter) { + wlr_log(WLR_ERROR, "Unable to create the viewporter interface"); + ret = 1; + goto end; + } + + presentation = wlr_presentation_create(server.wl_display, server.backend); + if(!presentation) { + wlr_log(WLR_ERROR, "Unable to create the presentation interface"); + ret = 1; + goto end; + } + wlr_scene_set_presentation(server.scene, presentation); + export_dmabuf_manager = wlr_export_dmabuf_manager_v1_create(server.wl_display); if(!export_dmabuf_manager) { @@ -347,17 +404,17 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { goto end; } - gamma_control_manager = - wlr_gamma_control_manager_v1_create(server.wl_display); - if(!gamma_control_manager) { - wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); + if(!wlr_primary_selection_v1_device_manager_create(server.wl_display)) { + wlr_log(WLR_ERROR, + "Unable to create the primary selection device manager"); ret = 1; goto end; } - compositor = wlr_compositor_create(server.wl_display, server.renderer); - if(!compositor) { - wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); + gamma_control_manager = + wlr_gamma_control_manager_v1_create(server.wl_display); + if(!gamma_control_manager) { + wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); ret = 1; goto end; } @@ -372,13 +429,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { server.new_xwayland_surface.notify = handle_xwayland_surface_new; wl_signal_add(&xwayland->events.new_surface, &server.new_xwayland_surface); - xcursor_manager = wlr_xcursor_manager_create(DEFAULT_XCURSOR, XCURSOR_SIZE); - if(!xcursor_manager) { - wlr_log(WLR_ERROR, "Cannot create XWayland XCursor manager"); - ret = 1; - goto end; - } - if(setenv("DISPLAY", xwayland->display_name, true) < 0) { wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland.", "Clients may not be able to connect"); @@ -387,18 +437,15 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { xwayland->display_name); } - if(wlr_xcursor_manager_load(xcursor_manager, 1)) { - wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme"); - } struct wlr_xcursor *xcursor = - wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1); + wlr_xcursor_manager_get_xcursor(server.seat->xcursor_manager, DEFAULT_XCURSOR, 1); + if(xcursor) { struct wlr_xcursor_image *image = xcursor->images[0]; wlr_xwayland_set_cursor(xwayland, image->buffer, image->width * 4, image->width, image->height, image->hotspot_x, image->hotspot_y); } - #endif const char *socket = wl_display_add_socket_auto(server.wl_display); @@ -418,15 +465,25 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.", "Clients may not be able to connect"); } else { - wlr_log(WLR_DEBUG, - "Cagebreak " CG_VERSION " is running on Wayland display %s", - socket); + fprintf(stderr, "Cagebreak " CG_VERSION " is running on Wayland display %s\n", socket); + } + +#if CG_HAS_XWAYLAND + wlr_xwayland_set_seat(xwayland, server.seat->seat); +#endif + + /* Place the cursor to the top left of the output layout. */ + wlr_cursor_warp(server.seat->cursor, NULL, 0, 0); + + + if(!drop_permissions()) { + ret = 1; + goto end; } /* Place the cursor to the topl left of the output layout. */ wlr_cursor_warp(server.seat->cursor, NULL, 0, 0); atexit(cleanup); - // server.wl_display->run = 1; return 0; end: cleanup(); @@ -571,5 +628,4 @@ destroy_output(char *line, struct cg_server *server) { --outpn; } } - it->damage_destroy.notify(&it->damage_destroy, NULL); } diff --git a/fuzz/fuzz-parse.c b/fuzz/fuzz-parse.c index 8aded78..d152f07 100644 --- a/fuzz/fuzz-parse.c +++ b/fuzz/fuzz-parse.c @@ -38,7 +38,7 @@ set_configuration(struct cg_server *server, char *content) { (line = strtok_r(NULL, "\n", &content)) != NULL; ++line_num) { line[strcspn(line, "\n")] = '\0'; if(*line != '\0' && *line != '#') { - char *errstr; + char *errstr=NULL; server->running = true; if(parse_rc_line(server, line, &errstr) != 0) { if(errstr != NULL) { @@ -56,10 +56,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 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; + char *str = malloc(sizeof(char) * size); + strncpy(str, (char *)data, size); + str[size - 1] = 0; set_configuration(&server, str); free(str); keybinding_list_free(server.keybindings); diff --git a/fuzz/meson.build b/fuzz/meson.build index b5ba1be..b8448bc 100644 --- a/fuzz/meson.build +++ b/fuzz/meson.build @@ -19,7 +19,7 @@ endif override_lib = shared_library('execl_override', [ 'execl_override.c' ], - dependencies: [ pixman,cairo,pango,pangocairo ], + dependencies: [ cairo,pango,pangocairo ], install: false ) diff --git a/keybinding.c b/keybinding.c index 416ecac..f809b34 100644 --- a/keybinding.c +++ b/keybinding.c @@ -87,6 +87,10 @@ keybinding_free(struct keybinding *keybinding, bool recursive) { free(keybinding->data.m_cfg->font); } break; + case KEYBINDING_DISPLAY_MESSAGE: + if(keybinding->data.c != NULL) { + free(keybinding->data.c); + } default: break; } @@ -1046,7 +1050,7 @@ print_keyboard_groups(struct cg_server *server) { struct dyn_str outp_str; outp_str.len = 0; outp_str.cur_pos = 0; - outp_str.str_arr = calloc((2 * ninps - 1) + 2, sizeof(char *)); + outp_str.str_arr = calloc((2 * ninps - 1) + 3, sizeof(char *)); print_str(&outp_str, "\"keyboards\": {"); struct cg_keyboard_group *it; uint32_t count = 0; @@ -1090,7 +1094,7 @@ print_input_devices(struct cg_server *server) { struct dyn_str outp_str; outp_str.len = 0; outp_str.cur_pos = 0; - outp_str.str_arr = calloc((2 * ninps - 1) + 2, sizeof(char *)); + outp_str.str_arr = calloc((2 * ninps - 1) + 3, sizeof(char *)); print_str(&outp_str, "\"input_devices\": {"); struct cg_input_device *it; uint32_t count = 0; @@ -1217,9 +1221,10 @@ keybinding_move_view_to_cycle_output(struct cg_server *server, bool reverse) { void keybinding_set_nws(struct cg_server *server, int nws) { struct cg_output *output; - int old_nws = server->nws; + unsigned int old_nws = server->nws; + server->nws = nws; wl_list_for_each(output, &server->outputs, link) { - for(unsigned int i = nws; i < server->nws; ++i) { + for(unsigned int i = nws; i < old_nws; ++i) { struct cg_view *view, *tmp; wl_list_for_each_safe(view, tmp, &output->workspaces[i]->views, link) { @@ -1244,7 +1249,7 @@ keybinding_set_nws(struct cg_server *server, int nws) { return; } output->workspaces = new_workspaces; - for(int i = server->nws; i < nws; ++i) { + for(int i = old_nws; i < nws; ++i) { output->workspaces[i] = full_screen_workspace(output); output->workspaces[i]->num = i; if(!output->workspaces[i]) { @@ -1257,10 +1262,10 @@ keybinding_set_nws(struct cg_server *server, int nws) { } if(output->curr_workspace >= nws) { + output->curr_workspace=0; workspace_focus(output, nws - 1); } } - server->nws = nws; seat_set_focus( server->seat, server->curr_output->workspaces[server->curr_output->curr_workspace] diff --git a/output.c b/output.c index ac8384e..379e9d1 100644 --- a/output.c +++ b/output.c @@ -540,11 +540,11 @@ 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); - output->workspaces[i]->num = i; if(!output->workspaces[i]) { wlr_log(WLR_ERROR, "Failed to allocate workspaces for output"); return; } + output->workspaces[i]->num = i; wl_list_init(&output->workspaces[i]->views); wl_list_init(&output->workspaces[i]->unmanaged_views); } diff --git a/workspace.c b/workspace.c index 3b2b8e9..a9b9734 100644 --- a/workspace.c +++ b/workspace.c @@ -126,6 +126,10 @@ workspace_free(struct cg_workspace *workspace) { void workspace_focus(struct cg_output *outp, int ws) { + if(ws>=outp->server->nws) { + wlr_log(WLR_ERROR,"Attempt to focus workspace %d, but only %d workspaces are available.",ws,outp->server->nws); + return; + } wlr_scene_node_place_above( &outp->bg->node, &outp->workspaces[outp->curr_workspace]->scene->node); wlr_scene_node_place_above(&outp->workspaces[ws]->scene->node,