From d0b1b3f63e7be1e47533f559d2968347b8797629 Mon Sep 17 00:00:00 2001
From: Grzegorz Sluja <grzegorz.sluja@iopsys.eu>
Date: Tue, 5 Dec 2023 09:29:06 +0100
Subject: [PATCH] Fix the memory leak in blob_buf

There were some places where blob_buf was allocated but never freed.
Valgrind found it in the following backtrace:

==18922== 166,400 bytes in 650 blocks are definitely lost in loss record 35 of 38
==18922==    at 0x488FDE4: realloc (vg_replace_malloc.c:1649)
==18922==    by 0x5E861A3: blob_buffer_grow (blob.c:26)
==18922==    by 0x5E86213: blob_buf_grow (blob.c:63)
==18922==    by 0x5E862CF: blob_add (blob.c:78)
==18922==    by 0x5E8633F: blob_buf_init (blob.c:97)
==18922==    by 0x5F5068F: ??? (in /usr/lib/asterisk/modules/chan_voicemngr.so)
---
 src/channels/chan_voicemngr.c | 56 ++++++++++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 10 deletions(-)

diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c
index 4526b99..7a5800c 100644
--- a/src/channels/chan_voicemngr.c
+++ b/src/channels/chan_voicemngr.c
@@ -426,12 +426,20 @@ static void endpt_get_codecs_cb(struct ubus_request *req, int type, struct blob_
 static void voicemngr_codecs_init(void)
 {
 	struct blob_buf bb;
+	int ret = 0;
 
 	memset(&bb, 0, sizeof(bb));
-	blob_buf_init(&bb, 0);
+	if(blob_buf_init(&bb, 0)) {
+		return;
+	}
 	blobmsg_add_u8(&bb, "effective", 0);
-	ubus_invoke(get_shared_context(__FUNCTION__), endpt_id, "codecs", bb.head,
+	ret = ubus_invoke(get_shared_context(__FUNCTION__), endpt_id, "codecs", bb.head,
 		endpt_get_codecs_cb, NULL, 2000);
+
+	if (ret)
+		ast_log(LOG_ERROR, "Error invoking method: %s %d\n", "codecs", ret);
+
+	blob_buf_free(&bb);
 }
 
 // codec data string to codec enum
@@ -652,7 +660,9 @@ static void endpt_signal(int line, char *signal, char *state, char *data) {
 
 	if (endpt_id) {
 		memset(&bb, 0, sizeof(bb));
-		blob_buf_init(&bb, 0);
+		if(blob_buf_init(&bb, 0)) {
+			return;
+		}
 
 		blobmsg_add_u32(&bb, "line", line);
 		blobmsg_add_string(&bb, "signal", signal);
@@ -661,7 +671,10 @@ static void endpt_signal(int line, char *signal, char *state, char *data) {
 			blobmsg_add_string(&bb, "data", data);
 
 		req = calloc(1, sizeof(struct ubus_request));
-		if (!req) return;
+		if (!req) {
+			blob_buf_free(&bb);
+			return;
+		}
 
 		ast_verbose("thread %d: ubus call endpt signal\n", ast_get_tid());
 		res = ubus_invoke_async(get_shared_context(__FUNCTION__), endpt_id, "signal", bb.head, req);
@@ -669,6 +682,7 @@ static void endpt_signal(int line, char *signal, char *state, char *data) {
 		if(res != UBUS_STATUS_OK) {
 			ast_log(LOG_ERROR, "Error invoking method: %s %d\n", "signal", res);
 			free(req);
+			blob_buf_free(&bb);
 			return;
 		}
 
@@ -676,6 +690,7 @@ static void endpt_signal(int line, char *signal, char *state, char *data) {
 		req->complete_cb = ubus_call_complete;
 		req->priv = NULL;
 		ubus_complete_request_async(get_shared_context(__FUNCTION__), req);
+		blob_buf_free(&bb);
 	}
 }
 
@@ -717,7 +732,9 @@ static void endpt_connection_data(int line, int id, const char *action, const st
 
 	if (endpt_id) {
 		memset(&bb, 0, sizeof(bb));
-		blob_buf_init(&bb, 0);
+		if(blob_buf_init(&bb, 0)) {
+			return;
+		}
 
 		blobmsg_add_u32(&bb, "line", line);
 		blobmsg_add_u32(&bb, "id", id);
@@ -734,13 +751,17 @@ static void endpt_connection_data(int line, int id, const char *action, const st
 		}
 
 		req = calloc(1, sizeof(struct ubus_request));
-		if (!req) return;
+		if (!req) {
+			blob_buf_free(&bb);
+			return;
+		}
 		ast_verbose("thread %d: ubus call endpt connection\n", ast_get_tid());
 		res = ubus_invoke_async(get_shared_context(__FUNCTION__), endpt_id, "connection", bb.head, req);
 
 		if(res != UBUS_STATUS_OK) {
 			ast_log(LOG_ERROR, "Error invoking method: %s %d\n", "connection", res);
 			free(req);
+			blob_buf_free(&bb);
 			return;
 		}
 
@@ -748,6 +769,7 @@ static void endpt_connection_data(int line, int id, const char *action, const st
 		req->complete_cb = ubus_call_complete;
 		req->priv = NULL;
 		ubus_complete_request_async(get_shared_context(__FUNCTION__), req);
+		blob_buf_free(&bb);
 	}
 }
 
@@ -4740,17 +4762,27 @@ static void endpt_get_count_cb(struct ubus_request *req,
 
 static int endpt_get_count(void) {
 	struct blob_buf bb;
+	int ret = 0;
 
 	endpt_id = get_ubus_endpt_id(0);
 	if(!endpt_id)
 		return -1;
 
 	memset(&bb, 0, sizeof(bb));
-	blob_buf_init(&bb, 0);
+	if(blob_buf_init(&bb, 0)) {
+		return -1;
+	}
 	blobmsg_add_u8(&bb, "effective", 0);
 
-	return (ubus_invoke(get_shared_context(__FUNCTION__), endpt_id, "count", bb.head,
-		endpt_get_count_cb, NULL, 2000) == UBUS_STATUS_OK ? 0 : -1);
+	ret = ubus_invoke(get_shared_context(__FUNCTION__), endpt_id, "count", bb.head,
+		endpt_get_count_cb, NULL, 2000);
+
+	if (ret)
+		ast_log(LOG_ERROR, "Error invoking method: %s %d\n", "count", ret);
+
+	blob_buf_free(&bb);
+
+	return ((ret == UBUS_STATUS_OK) ? 0 : -1);
 }
 
 static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struct blob_attr *msg) {
@@ -4912,7 +4944,9 @@ static int endpt_get_rtp_stats(int line) {
 	}
 
 	memset(&bb, 0, sizeof(bb));
-	blob_buf_init(&bb, 0);
+	if(blob_buf_init(&bb, 0)) {
+		return -1;
+	}
 
 	blobmsg_add_u32(&bb, "line", line);
 	blobmsg_add_u8(&bb, "reset", 1); // always reset RTP stats after get them
@@ -5025,9 +5059,11 @@ static int asterisk_call_status(struct ubus_context *ctx, struct ubus_object *ob
 			blobmsg_close_table(&blob, table_stats);
 			res = UBUS_STATUS_OK;
 		} else {
+			blob_buf_free(&blob);
 			return UBUS_STATUS_INVALID_ARGUMENT;
 		}
 	} else {
+		blob_buf_free(&blob);
 		return UBUS_STATUS_INVALID_ARGUMENT;
 	}
 
-- 
GitLab