Commit a950dc420b for asterisk.org

commit a950dc420b7b6075150c400a0a9b7b7b150044b9
Author: Alexandre Fournier <afournier@wazo.io>
Date:   Thu Jul 23 16:52:36 2026 -0400

    func_channel: add NULL checks on channel tech for dummy channels

    A dummy channel allocated with ast_dummy_channel_alloc() never gets a
    channel technology, so ast_channel_tech() returns NULL for it.

    func_channel_read() dereferences ast_channel_tech(chan)->type for
    CHANNEL(channeltype) without checking the tech for NULL, and
    func_channel_write_real() dereferences it the same way in its fallback
    branch. Both crash with a SIGSEGV on a dummy channel.

    This happens when CHANNEL(channeltype) is present in channelvars of
    ari.conf and the variable is evaluated on a dummy channel, e.g. when
    a voicemail is deposited for a mailbox that has an email address
    configured.

    Guard both dereferences. A dummy channel has no technology, so
    CHANNEL(channeltype) now reads as an empty string and a write falls
    through to the "Unknown or unavailable item requested" warning.

    This is very similar to the issue fixed by
    https://github.com/asterisk/asterisk/pull/1993

    Resolves: #2150

    AI disclaimer: Claude Opus 4.8 was used to find the cause of the crash
    and to find a solution.

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git a/funcs/func_channel.c b/funcs/func_channel.c
index 15ca38ff0d..739a4786ec 100644
--- a/funcs/func_channel.c
+++ b/funcs/func_channel.c
@@ -462,7 +462,8 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
 		locked_copy_string(chan, buf,
 			ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len);
 	} else if (!strcasecmp(data, "channeltype"))
-		locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
+		locked_copy_string(chan, buf,
+			ast_channel_tech(chan) ? ast_channel_tech(chan)->type : "", len);
 	else if (!strcasecmp(data, "accountcode"))
 		locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
 	else if (!strcasecmp(data, "checkhangup")) {
@@ -797,7 +798,8 @@ static int func_channel_write_real(struct ast_channel *chan, const char *functio
 		}
 	} else if (!strcasecmp(data, "tenantid")) {
 		ast_channel_tenantid_set(chan, value);
-	} else if (!ast_channel_tech(chan)->func_channel_write
+	} else if (!ast_channel_tech(chan)
+		 || !ast_channel_tech(chan)->func_channel_write
 		 || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
 		ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
 				data);