The code here is wrong, leaky, and inconsistent. We don't free,
unlink or clean up things when we should in every error path.

Centralize the data destruction so it's easier to keep track of
and easier to bug fix.
---
 src/wayland-server.c | 49 ++++++++++++++++++++++++-------------------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index 1c9d4d0..3e0fb25 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -840,6 +840,23 @@ wl_display_create(void)
        return display;
 }
 
+static void
+wl_socket_destroy(struct wl_socket *s)
+{
+       if (s->source)
+               wl_event_source_remove(s->source);
+       if (s->addr.sun_path[0])
+               unlink(s->addr.sun_path);
+       if (s->fd)
+               close(s->fd);
+       if (s->lock_addr[0])
+               unlink(s->lock_addr);
+       if (s->fd_lock)
+               close(s->fd_lock);
+
+       free(s);
+}
+
 WL_EXPORT void
 wl_display_destroy(struct wl_display *display)
 {
@@ -849,12 +866,7 @@ wl_display_destroy(struct wl_display *display)
        wl_signal_emit(&display->destroy_signal, display);
 
        wl_list_for_each_safe(s, next, &display->socket_list, link) {
-               wl_event_source_remove(s->source);
-               unlink(s->addr.sun_path);
-               close(s->fd);
-               unlink(s->lock_addr);
-               close(s->fd_lock);
-               free(s);
+               wl_socket_destroy(s);
        }
        wl_event_loop_destroy(display->loop);
 
@@ -1072,7 +1084,7 @@ wl_display_add_socket(struct wl_display *display, const 
char *name)
 
        s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
        if (s->fd < 0) {
-               free(s);
+               wl_socket_destroy(s);
                return -1;
        }
 
@@ -1090,8 +1102,7 @@ wl_display_add_socket(struct wl_display *display, const 
char *name)
        if (name_size > (int)sizeof s->addr.sun_path) {
                wl_log("error: socket path \"%s/%s\" plus null terminator"
                       " exceeds 108 bytes\n", runtime_dir, name);
-               close(s->fd);
-               free(s);
+               wl_socket_destroy(s);
                /* to prevent programs reporting
                 * "failed to add socket: Success" */
                errno = ENAMETOOLONG;
@@ -1100,28 +1111,20 @@ wl_display_add_socket(struct wl_display *display, const 
char *name)
 
        s->fd_lock = get_socket_lock(s);
        if (s->fd_lock < 0) {
-               close(s->fd);
-               free(s);
+               wl_socket_destroy(s);
                return -1;
        }
 
        size = offsetof (struct sockaddr_un, sun_path) + name_size;
        if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
                wl_log("bind() failed with error: %m\n");
-               close(s->fd);
-               unlink(s->lock_addr);
-               close(s->fd_lock);
-               free(s);
+               wl_socket_destroy(s);
                return -1;
        }
 
        if (listen(s->fd, 1) < 0) {
                wl_log("listen() failed with error: %m\n");
-               unlink(s->addr.sun_path);
-               close(s->fd);
-               unlink(s->lock_addr);
-               close(s->fd_lock);
-               free(s);
+               wl_socket_destroy(s);
                return -1;
        }
 
@@ -1129,11 +1132,7 @@ wl_display_add_socket(struct wl_display *display, const 
char *name)
                                         WL_EVENT_READABLE,
                                         socket_data, display);
        if (s->source == NULL) {
-               unlink(s->addr.sun_path);
-               close(s->fd);
-               unlink(s->lock_addr);
-               close(s->fd_lock);
-               free(s);
+               wl_socket_destroy(s);
                return -1;
        }
        wl_list_insert(display->socket_list.prev, &s->link);
-- 
2.0.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to