[Asterisk-code-review] main/pbx_variables.c: Better parsing of variable name and value ... (asterisk[16])

Leandro Dardini asteriskteam at digium.com
Tue Jan 19 14:37:15 CST 2021


Leandro Dardini has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/15331 )


Change subject: main/pbx_variables.c: Better parsing of variable name and value                       separator for Set command main/utils.c: Added a subroutine to return name and value from               Set command argument
......................................................................

main/pbx_variables.c: Better parsing of variable name and value
                      separator for Set command
main/utils.c: Added a subroutine to return name and value from
              Set command argument

The variable name and value of a Set command are separated by a
=, but the = character may appear in the variable name portion as
a parameter for a function, like any ODBC_* func_odbc.conf
function, so better handling of quotes, parenthesis, and brackets
was needed.

ASTERISK-29239 #close

Change-Id: I7cd3bc6118033530ad00ae4b6bdad97b6b349b6f
---
M include/asterisk/utils.h
M main/pbx_variables.c
M main/utils.c
3 files changed, 69 insertions(+), 9 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/31/15331/1

diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h
index 0ee11ee..54da45d 100644
--- a/include/asterisk/utils.h
+++ b/include/asterisk/utils.h
@@ -928,6 +928,12 @@
  */
 int ast_check_ipv6(void);
 
+/*!
+ *\brief Parse a name = value assignment pair.
+ *\return Returns -1 if there is no valid assignment in the string.
+ */
+int ast_parse_name_value(const char *input, char **name, char **value);
+
 enum ast_fd_flag_operation {
 	AST_FD_FLAG_SET,
 	AST_FD_FLAG_CLEAR,
diff --git a/main/pbx_variables.c b/main/pbx_variables.c
index 91b5bbb..22d14b2 100644
--- a/main/pbx_variables.c
+++ b/main/pbx_variables.c
@@ -1128,23 +1128,22 @@
 
 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
 {
-	char *name, *value, *mydata;
+        char *name = NULL;
+        char *value = NULL;
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
 		return 0;
 	}
 
-	mydata = ast_strdupa(data);
-	name = strsep(&mydata, "=");
-	value = mydata;
-	if (!value) {
-		ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
-		return 0;
-	}
+	/* We don't know how much of "data" is the name and how much is the value so we'll use the worst case */
+	name = ast_alloca(strlen(data) + 1);
+	value = ast_alloca(strlen(data) + 1);
+
+	ast_parse_name_value(data,&name,&value);
 
 	if (strchr(name, ' ')) {
-		ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
+		ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, value);
 	}
 
 	pbx_builtin_setvar_helper(chan, name, value);
diff --git a/main/utils.c b/main/utils.c
index 827ee2e..aa44cd5 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -2372,6 +2372,61 @@
 	return 0;
 }
 
+/*!
+ *\brief Parse a name = value assignment pair.
+ *\return Returns -1 if there is no valid assignment in the string.
+ */
+int ast_parse_name_value(const char *input, char **name, char **value)
+{
+        char *mydata = NULL;
+        char *scan = NULL;
+	int paren = 0;
+	int quote = 0;
+	int bracket = 0;
+	int ret = 0;
+
+	if (ast_strlen_zero(input)) {
+	  ast_log(LOG_ERROR, "Input must be not NULL");
+	  ret = -1;
+	}
+
+	mydata = ast_strdupa(input);
+
+	scan = mydata;
+
+	for (; *scan; scan++) {
+          if (*scan == '(') {
+            paren++;
+          } else if (*scan == ')') {
+            if (paren) {
+              paren--;
+            }
+          } else if (*scan == '[') {
+            bracket++;
+          } else if (*scan == ']') {
+            if (bracket) {
+              bracket--;
+            }
+          } else if (*scan == '"') {
+            quote = quote ? 0 : 1;
+          } else if (*scan == '\\') {
+            scan++;
+          } else if ((*scan == '=') && !paren && !quote && !bracket) {
+            *scan++ = '\0';
+            strcpy(*value, scan);
+            strcpy(*name, mydata);
+            break;
+          }
+        }
+
+	if (!*value) {
+		ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
+		ret = -1;
+	}
+
+	return ret;
+}
+
 int ast_get_tid(void)
 {
 	int ret = -1;

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/15331
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-Change-Id: I7cd3bc6118033530ad00ae4b6bdad97b6b349b6f
Gerrit-Change-Number: 15331
Gerrit-PatchSet: 1
Gerrit-Owner: Leandro Dardini <ldardini at gmail.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210119/f3b566cf/attachment.html>


More information about the asterisk-code-review mailing list