From c35760cd50d6c5084a1265f8d8c4aa7a5557c0d4 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Sat, 6 Jun 2015 14:05:55 +0200 Subject: [PATCH] Fix possible segfaults when header allocation fails This fixes some possible segfaults that could happen if the header (re)allocation fails. --- src/format.c | 14 +++++++++++--- src/source.c | 18 ++++++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/format.c b/src/format.c index 6ac2a7af..8e7dce4e 100644 --- a/src/format.c +++ b/src/format.c @@ -282,6 +282,14 @@ int format_advance_queue(source_t *source, client_t *client) } +/* Prepare headers + * If any error occurs in this function, return -1 + * Do not send a error to the client using client_send_error + * here but instead set client->respcode to 500. + * Else client_send_error will destroy and free the client and all + * calling functions will use a already freed client struct and + * cause a segfault! + */ static int format_prepare_headers (source_t *source, client_t *client) { unsigned remaining; @@ -297,7 +305,7 @@ static int format_prepare_headers (source_t *source, client_t *client) bytes = util_http_build_header(ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL, source, client); if (bytes == -1) { ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); - client_send_error(client, 500, 0, "Header generation failed."); + client->respcode = 500; return -1; } else if ((bytes + 1024) >= remaining) { /* we don't know yet how much to follow but want at least 1kB free space */ void *new_ptr = realloc(ptr, bytes + 1024); @@ -308,12 +316,12 @@ static int format_prepare_headers (source_t *source, client_t *client) bytes = util_http_build_header(ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL, source, client); if (bytes == -1 ) { ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); - client_send_error(client, 500, 0, "Header generation failed."); + client->respcode = 500; return -1; } } else { ICECAST_LOG_ERROR("Client buffer reallocation failed. Dropping client."); - client_send_error(client, 500, 0, "Buffer reallocation failed."); + client->respcode = 500; return -1; } } diff --git a/src/source.c b/src/source.c index 1811ec6e..8ae0cbdb 100644 --- a/src/source.c +++ b/src/source.c @@ -952,12 +952,18 @@ static int _free_client(void *key) { client_t *client = (client_t *)key; - /* if no response has been sent then send a 404 */ - if (client->respcode == 0) - client_send_error(client, 404, 0, "Mount unavailable"); - else - client_destroy(client); - + switch (client->respcode) { + case 0: + /* if no response has been sent then send a 404 */ + client_send_error(client, 404, 0, "Mount unavailable"); + break; + case 500: + client_send_error(client, 500, 0, "Stream preparation error"); + break; + default: + client_destroy(client); + break; + } return 1; }