]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
resource_channels.c: Fix memory leak in ast_ari_channels_external_media.
authorGeorge Joseph <gjoseph@sangoma.com>
Tue, 4 Feb 2025 20:00:16 +0000 (13:00 -0700)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 11 Feb 2025 23:31:21 +0000 (23:31 +0000)
Between ast_ari_channels_external_media(), external_media_rtp_udp(),
and external_media_audiosocket_tcp(), the `variables` structure being passed
around wasn't being cleaned up properly when there was a failure.

* In ast_ari_channels_external_media(), the `variables` structure is now
  defined with RAII_VAR to ensure it always gets cleaned up.

* The ast_variables_destroy() call was removed from external_media_rtp_udp().

* The ast_variables_destroy() call was removed from
  external_media_audiosocket_tcp(), its `endpoint` allocation was changed to
  to use ast_asprintf() as external_media_rtp_udp() does, and it now
  returns an error on failure.

* ast_ari_channels_external_media() now checks the new return code from
  external_media_audiosocket_tcp() and sets the appropriate error response.

Resolves: #1109

res/ari/resource_channels.c

index 194abc398b6586f5abce4bcd26fbc4fba377d45b..bcb2871c4ec7f4e14cb7d4a385cc1d138fbf584e 100644 (file)
@@ -2111,7 +2111,6 @@ static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *a
                NULL,
                args->format,
                response);
-       ast_variables_destroy(variables);
 
        ast_free(endpoint);
 
@@ -2129,24 +2128,23 @@ static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *a
        return 0;
 }
 
-static void external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args,
+static int external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args,
        struct ast_variable *variables,
        struct ast_ari_response *response)
 {
-       size_t endpoint_len;
        char *endpoint;
        struct ast_channel *chan;
        struct varshead *vars;
 
        if (ast_strlen_zero(args->data)) {
                ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
-               return;
+               return 1;
        }
 
-       endpoint_len = strlen("AudioSocket/") + strlen(args->external_host) + 1 + strlen(args->data) + 1;
-       endpoint = ast_alloca(endpoint_len);
-       /* The UUID is stored in the arbitrary data field */
-       snprintf(endpoint, endpoint_len, "AudioSocket/%s/%s", args->external_host, args->data);
+       if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
+               args->external_host, args->data) == -1) {
+               return 1;
+       }
 
        chan = ari_channels_handle_originate_with_id(
                endpoint,
@@ -2164,10 +2162,11 @@ static void external_media_audiosocket_tcp(struct ast_ari_channels_external_medi
                NULL,
                args->format,
                response);
-       ast_variables_destroy(variables);
+
+       ast_free(endpoint);
 
        if (!chan) {
-               return;
+               return 1;
        }
 
        ast_channel_lock(chan);
@@ -2177,6 +2176,7 @@ static void external_media_audiosocket_tcp(struct ast_ari_channels_external_medi
        }
        ast_channel_unlock(chan);
        ast_channel_unref(chan);
+       return 0;
 }
 
 #include "asterisk/config.h"
@@ -2185,7 +2185,7 @@ static void external_media_audiosocket_tcp(struct ast_ari_channels_external_medi
 void ast_ari_channels_external_media(struct ast_variable *headers,
        struct ast_ari_channels_external_media_args *args, struct ast_ari_response *response)
 {
-       struct ast_variable *variables = NULL;
+       RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
        char *external_host;
        char *host = NULL;
        char *port = NULL;
@@ -2245,7 +2245,11 @@ void ast_ari_channels_external_media(struct ast_variable *headers,
                                "An internal error prevented this request from being handled");
                }
        } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
-               external_media_audiosocket_tcp(args, variables, response);
+               if (external_media_audiosocket_tcp(args, variables, response)) {
+                       ast_ari_response_error(
+                               response, 500, "Internal Server Error",
+                               "An internal error prevented this request from being handled");
+               }
        } else {
                ast_ari_response_error(
                        response, 501, "Not Implemented",