From 5cc7342606dbbd5e6932b39e6b1b5645164669bf Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Tue, 15 Aug 2017 07:56:47 +0200 Subject: [PATCH] Prevent alloc errors from crashing Resolves #76 --- backend/libinput/events.c | 50 +++++++++++++++++++++++++++++++++++-- backend/libinput/keyboard.c | 6 +++-- backend/multi/backend.c | 6 ++++- backend/wayland/wl_seat.c | 2 +- examples/compositor/main.c | 4 +++ examples/rotation.c | 9 +++++++ examples/tablet.c | 5 ++++ examples/touch.c | 9 +++++++ render/gles2/renderer.c | 6 +++-- render/gles2/texture.c | 6 +++-- types/wlr_surface.c | 6 ++++- types/wlr_xdg_shell_v6.c | 6 +++-- util/list.c | 7 ++++++ 13 files changed, 109 insertions(+), 13 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 0e434b7c..37ec6f4c 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -39,8 +39,10 @@ static struct wlr_input_device *allocate_device( int vendor = libinput_device_get_id_vendor(libinput_dev); int product = libinput_device_get_id_product(libinput_dev); const char *name = libinput_device_get_name(libinput_dev); - struct wlr_libinput_input_device *wlr_libinput_dev = - calloc(1, sizeof(struct wlr_libinput_input_device)); + struct wlr_libinput_input_device *wlr_libinput_dev; + if (!(wlr_libinput_dev = calloc(1, sizeof(struct wlr_libinput_input_device)))) { + return NULL; + } struct wlr_input_device *wlr_dev = &wlr_libinput_dev->wlr_input_device; wlr_libinput_dev->handle = libinput_dev; libinput_device_ref(libinput_dev); @@ -63,36 +65,74 @@ static void handle_device_added(struct wlr_libinput_backend *backend, int product = libinput_device_get_id_product(libinput_dev); const char *name = libinput_device_get_name(libinput_dev); list_t *wlr_devices = list_create(); + if (!wlr_devices) { + goto fail; + } wlr_log(L_DEBUG, "Added %s [%d:%d]", name, vendor, product); if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { struct wlr_input_device *wlr_dev = allocate_device(backend, libinput_dev, wlr_devices, WLR_INPUT_DEVICE_KEYBOARD); + if (!wlr_dev) { + goto fail; + } wlr_dev->keyboard = wlr_libinput_keyboard_create(libinput_dev); + if (!wlr_dev->keyboard) { + free(wlr_dev); + goto fail; + } wl_signal_emit(&backend->backend.events.input_add, wlr_dev); } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_POINTER)) { struct wlr_input_device *wlr_dev = allocate_device(backend, libinput_dev, wlr_devices, WLR_INPUT_DEVICE_POINTER); + if (!wlr_dev) { + goto fail; + } wlr_dev->pointer = wlr_libinput_pointer_create(libinput_dev); + if (!wlr_dev->pointer) { + free(wlr_dev); + goto fail; + } wl_signal_emit(&backend->backend.events.input_add, wlr_dev); } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) { struct wlr_input_device *wlr_dev = allocate_device(backend, libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TOUCH); + if (!wlr_dev) { + goto fail; + } wlr_dev->touch = wlr_libinput_touch_create(libinput_dev); + if (!wlr_dev->touch) { + free(wlr_dev); + goto fail; + } wl_signal_emit(&backend->backend.events.input_add, wlr_dev); } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { struct wlr_input_device *wlr_dev = allocate_device(backend, libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_TOOL); + if (!wlr_dev) { + goto fail; + } wlr_dev->tablet_tool = wlr_libinput_tablet_tool_create(libinput_dev); + if (!wlr_dev->tablet_tool) { + free(wlr_dev); + goto fail; + } wl_signal_emit(&backend->backend.events.input_add, wlr_dev); } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { struct wlr_input_device *wlr_dev = allocate_device(backend, libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_PAD); + if (!wlr_dev) { + goto fail; + } wlr_dev->tablet_pad = wlr_libinput_tablet_pad_create(libinput_dev); + if (!wlr_dev->tablet_pad) { + free(wlr_dev); + goto fail; + } wl_signal_emit(&backend->backend.events.input_add, wlr_dev); } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) { @@ -108,6 +148,12 @@ static void handle_device_added(struct wlr_libinput_backend *backend, } else { list_free(wlr_devices); } + return; + +fail: + wlr_log(L_ERROR, "Could not allocate new device"); + list_foreach(wlr_devices, free); + list_free(wlr_devices); } static void handle_device_removed(struct wlr_libinput_backend *backend, diff --git a/backend/libinput/keyboard.c b/backend/libinput/keyboard.c index db4ac0ed..1c52a6b8 100644 --- a/backend/libinput/keyboard.c +++ b/backend/libinput/keyboard.c @@ -32,8 +32,10 @@ struct wlr_keyboard_impl impl = { struct wlr_keyboard *wlr_libinput_keyboard_create( struct libinput_device *libinput_dev) { assert(libinput_dev); - struct wlr_libinput_keyboard *wlr_libinput_kb = - calloc(1, sizeof(struct wlr_libinput_keyboard)); + struct wlr_libinput_keyboard *wlr_libinput_kb; + if (!(wlr_libinput_kb= calloc(1, sizeof(struct wlr_libinput_keyboard)))) { + return NULL; + } wlr_libinput_kb->libinput_dev = libinput_dev; libinput_device_ref(libinput_dev); libinput_device_led_update(libinput_dev, 0); diff --git a/backend/multi/backend.c b/backend/multi/backend.c index 9afca47d..290b9678 100644 --- a/backend/multi/backend.c +++ b/backend/multi/backend.c @@ -115,7 +115,11 @@ void wlr_multi_backend_add(struct wlr_backend *_multi, assert(wlr_backend_is_multi(_multi)); struct wlr_multi_backend *multi = (struct wlr_multi_backend *)_multi; - struct subbackend_state *sub = calloc(1, sizeof(struct subbackend_state)); + struct subbackend_state *sub; + if (!(sub = calloc(1, sizeof(struct subbackend_state)))) { + wlr_log(L_ERROR, "Could not add backend: allocation failed"); + return; + } sub->backend = backend; sub->container = &multi->backend; diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index 6e645a58..3742d4fb 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -239,7 +239,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, struct wlr_input_device *wlr_device = allocate_device(backend, WLR_INPUT_DEVICE_KEYBOARD); if (!wlr_device) { - wlr_log(L_ERROR, "Unable to allocate wl_pointer device"); + wlr_log(L_ERROR, "Unable to allocate wl_keyboard device"); return; } wlr_device->keyboard = calloc(1, sizeof(struct wlr_keyboard)); diff --git a/examples/compositor/main.c b/examples/compositor/main.c index 933e27c7..9b8a041c 100644 --- a/examples/compositor/main.c +++ b/examples/compositor/main.c @@ -70,6 +70,10 @@ int main() { compositor_init(&compositor); state.renderer = wlr_gles2_renderer_init(compositor.backend); + if (!state.renderer) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } wl_display_init_shm(compositor.display); wl_compositor_init(compositor.display, &state.compositor, state.renderer); wl_shell_init(compositor.display, &state.shell); diff --git a/examples/rotation.c b/examples/rotation.c index e4c3f87f..fc12558f 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "shared.h" #include "cat.h" @@ -205,7 +206,15 @@ int main(int argc, char *argv[]) { compositor_init(&compositor); state.renderer = wlr_gles2_renderer_init(compositor.backend); + if (!state.renderer) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } state.cat_texture = wlr_render_texture_init(state.renderer); + if (!state.cat_texture) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } wlr_texture_upload_pixels(state.cat_texture, WL_SHM_FORMAT_ABGR8888, cat_tex.width, cat_tex.width, cat_tex.height, cat_tex.pixel_data); diff --git a/examples/tablet.c b/examples/tablet.c index 0651efde..17653885 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "shared.h" #include "cat.h" @@ -153,6 +154,10 @@ int main(int argc, char *argv[]) { compositor_init(&compositor); state.renderer = wlr_gles2_renderer_init(compositor.backend); + if (!state.renderer) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } compositor_run(&compositor); wlr_renderer_destroy(state.renderer); diff --git a/examples/touch.c b/examples/touch.c index 9dd2fe57..a32c76ba 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "shared.h" #include "cat.h" @@ -105,7 +106,15 @@ int main(int argc, char *argv[]) { compositor_init(&compositor); state.renderer = wlr_gles2_renderer_init(compositor.backend); + if (!state.renderer) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } state.cat_texture = wlr_render_texture_init(state.renderer); + if (!state.cat_texture) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } wlr_texture_upload_pixels(state.cat_texture, WL_SHM_FORMAT_ARGB8888, cat_tex.width, cat_tex.width, cat_tex.height, cat_tex.pixel_data); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 75a47187..27f3d33e 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -240,8 +240,10 @@ static struct wlr_renderer_impl wlr_renderer_impl = { struct wlr_renderer *wlr_gles2_renderer_init(struct wlr_backend *backend) { init_globals(); - struct wlr_gles2_renderer *renderer = - calloc(1, sizeof(struct wlr_gles2_renderer)); + struct wlr_gles2_renderer *renderer; + if (!(renderer = calloc(1, sizeof(struct wlr_gles2_renderer)))) { + return NULL; + } wlr_renderer_init(&renderer->wlr_renderer, &wlr_renderer_impl); if (backend) { struct wlr_egl *egl = wlr_backend_get_egl(backend); diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 1e80a8d6..041625fd 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -252,8 +252,10 @@ static struct wlr_texture_impl wlr_texture_impl = { }; struct wlr_texture *gles2_texture_init(struct wlr_egl *egl) { - struct wlr_gles2_texture *texture = - calloc(1, sizeof(struct wlr_gles2_texture)); + struct wlr_gles2_texture *texture; + if (!(texture = calloc(1, sizeof(struct wlr_gles2_texture)))) { + return NULL; + } wlr_texture_init(&texture->wlr_texture, &wlr_texture_impl); texture->egl = egl; return &texture->wlr_texture; diff --git a/types/wlr_surface.c b/types/wlr_surface.c index cc3b429d..1110ef06 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -200,7 +200,11 @@ static void destroy_surface(struct wl_resource *resource) { struct wlr_surface *wlr_surface_create(struct wl_resource *res, struct wlr_renderer *renderer) { - struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface)); + struct wlr_surface *surface; + if (!(surface = calloc(1, sizeof(struct wlr_surface)))) { + wl_resource_post_no_memory(res); + return NULL; + } surface->renderer = renderer; surface->texture = wlr_render_texture_init(renderer); surface->resource = res; diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 46f1c98e..2aad1551 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -141,8 +141,10 @@ static void xdg_shell_get_xdg_surface(struct wl_client *client, struct wl_resource *_xdg_shell, uint32_t id, struct wl_resource *_surface) { struct wlr_xdg_shell_v6 *xdg_shell = wl_resource_get_user_data(_xdg_shell); - struct wlr_xdg_surface_v6 *surface = - calloc(1, sizeof(struct wlr_xdg_surface_v6)); + struct wlr_xdg_surface_v6 *surface; + if (!(surface = calloc(1, sizeof(struct wlr_xdg_surface_v6)))) { + return; + } surface->surface = _surface; surface->resource = wl_resource_create(client, &zxdg_surface_v6_interface, wl_resource_get_version(_xdg_shell), id); diff --git a/util/list.c b/util/list.c index 94159036..279d2ab5 100644 --- a/util/list.c +++ b/util/list.c @@ -6,9 +6,16 @@ list_t *list_create(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); + if (!list->items) { + free(list); + return NULL; + } return list; }