diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2020-10-31 17:33:11 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2020-10-31 17:34:32 +0100 |
commit | 32c99c9d66fb210a5ea372c4b90dfdcd96e25955 (patch) | |
tree | 42750b14a697444ed29bd90b2853c94e9b0a6415 /kike.c | |
parent | cd7133e1735906d941f5f2ccc2faa083360841d6 (diff) | |
download | xK-32c99c9d66fb210a5ea372c4b90dfdcd96e25955.tar.gz xK-32c99c9d66fb210a5ea372c4b90dfdcd96e25955.tar.xz xK-32c99c9d66fb210a5ea372c4b90dfdcd96e25955.zip |
kike: avoid crash with a wildcard address
A most unfortunate 06d3b3b regression, mostly stemming from
forgetting why the `break` was in place and not documenting it.
Diffstat (limited to 'kike.c')
-rw-r--r-- | kike.c | 29 |
1 files changed, 20 insertions, 9 deletions
@@ -614,7 +614,8 @@ struct server_context { int *listen_fds; ///< Listening socket FD's struct poller_fd *listen_events; ///< New connections available - size_t n_listen_fds; ///< Number of listening sockets + size_t listen_len; ///< Number of listening sockets + size_t listen_alloc; ///< How many we've allocated time_t started; ///< When has the server been started @@ -695,7 +696,7 @@ server_context_free (struct server_context *self) { str_map_free (&self->config); - for (size_t i = 0; i < self->n_listen_fds; i++) + for (size_t i = 0; i < self->listen_len; i++) { poller_fd_reset (&self->listen_events[i]); xclose (self->listen_fds[i]); @@ -746,12 +747,12 @@ irc_initiate_quit (struct server_context *ctx) { print_status ("shutting down"); - for (size_t i = 0; i < ctx->n_listen_fds; i++) + for (size_t i = 0; i < ctx->listen_len; i++) { poller_fd_reset (&ctx->listen_events[i]); xclose (ctx->listen_fds[i]); } - ctx->n_listen_fds = 0; + ctx->listen_len = 0; for (struct client *iter = ctx->clients; iter; iter = iter->next) if (!iter->closing_link) @@ -3852,16 +3853,19 @@ irc_listen_resolve (struct server_context *ctx, int fd; for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next) { + if (ctx->listen_len == ctx->listen_alloc) + break; + if ((fd = irc_listen (gai_iter)) == -1) continue; set_blocking (fd, false); - struct poller_fd *event = &ctx->listen_events[ctx->n_listen_fds]; + struct poller_fd *event = &ctx->listen_events[ctx->listen_len]; *event = poller_fd_make (&ctx->poller, fd); event->dispatcher = (poller_fd_fn) on_irc_client_available; event->user_data = ctx; - ctx->listen_fds[ctx->n_listen_fds++] = fd; + ctx->listen_fds[ctx->listen_len++] = fd; poller_fd_set (event, POLLIN); } freeaddrinfo (gai_result); @@ -3882,13 +3886,20 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e) struct strv ports = strv_make (); cstr_split (bind_port, ",", true, &ports); - ctx->listen_fds = xcalloc (ports.len, sizeof *ctx->listen_fds); - ctx->listen_events = xcalloc (ports.len, sizeof *ctx->listen_events); + + // For C and simplicity's sake let's assume that the host will resolve + // to at most two different addresses: IPv4 and IPv6 in case it is NULL + ctx->listen_alloc = ports.len * 2; + + ctx->listen_fds = + xcalloc (ctx->listen_alloc, sizeof *ctx->listen_fds); + ctx->listen_events = + xcalloc (ctx->listen_alloc, sizeof *ctx->listen_events); for (size_t i = 0; i < ports.len; i++) irc_listen_resolve (ctx, bind_host, ports.vector[i], &gai_hints); strv_free (&ports); - if (!ctx->n_listen_fds) + if (!ctx->listen_len) { error_set (e, "%s: %s", "network setup failed", "no ports to listen on"); |