mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	pbx_variables.c: Create real channel for "dialplan eval function".
"dialplan eval function" has been using a dummy channel for function evaluation, much like many of the unit tests. However, sometimes, this can cause issues for functions that are not expecting dummy channels. As an example, ast_channel_tech(chan) is NULL on such channels, and ast_channel_tech(chan)->type consequently results in a NULL dereference. Normally, functions do not worry about this since channels executing dialplan aren't dummy channels. While some functions are better about checking for these sorts of edge cases, use a real channel with a dummy technology to make this CLI command inherently safe for any dialplan function that could be evaluated from the CLI. Resolves: #1434
This commit is contained in:
		| @@ -39,6 +39,7 @@ | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/paths.h" | ||||
| #include "asterisk/pbx.h" | ||||
| #include "asterisk/format_cache.h" | ||||
| #include "asterisk/stasis_channels.h" | ||||
| #include "asterisk/test.h" | ||||
| #include "pbx_private.h" | ||||
| @@ -984,13 +985,19 @@ static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cl | ||||
| 	return CLI_SUCCESS; | ||||
| } | ||||
|  | ||||
| static const struct ast_channel_tech mock_channel_tech = { | ||||
| }; | ||||
|  | ||||
| static int cli_chan = 0; | ||||
|  | ||||
| /*! \brief CLI support for executing function */ | ||||
| static char *handle_eval_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| 	struct ast_channel *c = NULL; | ||||
| 	char *fn, *substituted; | ||||
| 	const char *fn, *substituted; | ||||
| 	int ret; | ||||
| 	char workspace[1024]; | ||||
| 	RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); | ||||
|  | ||||
| 	switch (cmd) { | ||||
| 	case CLI_INIT: | ||||
| @@ -1010,19 +1017,51 @@ static char *handle_eval_function(struct ast_cli_entry *e, int cmd, struct ast_c | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	c = ast_dummy_channel_alloc(); | ||||
| 	if (!c) { | ||||
| 		ast_cli(a->fd, "Unable to allocate bogus channel for function evaluation.\n"); | ||||
| 	if (a->argc != e->args + 1 && a->argc != e->args + 2) { | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); | ||||
| 	if (!caps) { | ||||
| 		ast_log(LOG_WARNING, "Could not allocate an empty format capabilities structure\n"); | ||||
| 		return CLI_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	fn = (char *) a->argv[3]; | ||||
| 	if (ast_format_cap_append(caps, ast_format_ulaw, 0)) { | ||||
| 		ast_log(LOG_WARNING, "Failed to append a ulaw format to capabilities for channel nativeformats\n"); | ||||
| 		return CLI_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_format_cap_append(caps, ast_format_alaw, 0)) { | ||||
| 		ast_log(LOG_WARNING, "Failed to append an alaw format to capabilities for channel nativeformats\n"); | ||||
| 		return CLI_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_format_cap_append(caps, ast_format_h264, 0)) { | ||||
| 		ast_log(LOG_WARNING, "Failed to append an h264 format to capabilities for channel nativeformats\n"); | ||||
| 		return CLI_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	c = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "CLIEval/%d", ++cli_chan); | ||||
| 	if (!c) { | ||||
| 		ast_cli(a->fd, "Unable to allocate mock channel for application execution.\n"); | ||||
| 		return CLI_FAILURE; | ||||
| 	} | ||||
| 	ast_channel_tech_set(c, &mock_channel_tech); | ||||
| 	ast_channel_nativeformats_set(c, caps); | ||||
| 	ast_channel_set_writeformat(c, ast_format_slin); | ||||
| 	ast_channel_set_rawwriteformat(c, ast_format_slin); | ||||
| 	ast_channel_set_readformat(c, ast_format_slin); | ||||
| 	ast_channel_set_rawreadformat(c, ast_format_slin); | ||||
| 	ast_channel_unlock(c); | ||||
|  | ||||
| 	fn = a->argv[3]; | ||||
| 	pbx_substitute_variables_helper(c, fn, workspace, sizeof(workspace)); | ||||
| 	substituted = ast_strdupa(workspace); | ||||
| 	workspace[0] = '\0'; | ||||
| 	ret = ast_func_read(c, substituted, workspace, sizeof(workspace)); | ||||
|  | ||||
| 	c = ast_channel_unref(c); | ||||
| 	ast_hangup(c); /* no need to unref separately */ | ||||
|  | ||||
| 	ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret); | ||||
| 	ast_cli(a->fd, "Result: %s\n", workspace); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user