From 1313c1284700f2cb9882b4390989e10a4b51df00 Mon Sep 17 00:00:00 2001 From: Richard Mudgett <rmudgett@digium.com> Date: Tue, 20 Sep 2011 22:54:21 +0000 Subject: [PATCH] Merged revisions 337119 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/10 ........ r337119 | rmudgett | 2011-09-20 17:47:45 -0500 (Tue, 20 Sep 2011) | 16 lines Fix crash with STRREPLACE function. The ast_func_read() function calls the .read2 callback with the len parameter set to zero indicating no size restrictions on the supplied ast_str buffer. The value was used to dimension a local starts[] array with the array subsequently used. * Reworked the strreplace() function to perform the string replacement in a straight forward manner. Eliminated the need for the starts[] array. (closes issue ASTERISK-18545) Reported by: Federico Alves Patches: jira_asterisk_18545_v10.patch (license #5621) patch uploaded by rmudgett Tested by: rmudgett, Federico Alves ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337123 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- funcs/func_strings.c | 87 +++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/funcs/func_strings.c b/funcs/func_strings.c index d9d0320314..5d7569bfef 100644 --- a/funcs/func_strings.c +++ b/funcs/func_strings.c @@ -859,14 +859,12 @@ static struct ast_custom_function replace_function = { static int strreplace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len) { - char *starts[len]; /* marks starts of substrings */ char *varsubstr; /* substring for input var */ - int count_len = 0; /* counter for starts */ - char *p; /* tracks position of cursor for search and replace */ + char *start; /* Starting pos of substring search. */ + char *end; /* Ending pos of substring search. */ int find_size; /* length of given find-string */ - int max_matches; /* number of matches we find before terminating search */ - - int x; /* loop counter */ + unsigned max_matches; /* number of matches we find before terminating search */ + unsigned count; /* loop counter */ struct ast_str *str = ast_str_thread_get(&result_buf, 16); /* Holds the data obtained from varname */ AST_DECLARE_APP_ARGS(args, @@ -874,16 +872,25 @@ static int strreplace(struct ast_channel *chan, const char *cmd, char *data, str AST_APP_ARG(find_string); AST_APP_ARG(replace_string); AST_APP_ARG(max_replacements); + AST_APP_ARG(other); /* Any remining unused arguments */ ); - AST_STANDARD_APP_ARGS(args, data); + /* Guarantee output string is empty to start with. */ + ast_str_reset(*buf); - if (!str) { /* If we failed to allocate str, forget it. We failed. */ + if (!str) { + /* We failed to allocate str, forget it. We failed. */ return -1; } - if (args.argc < 2) { /* Didn't receive enough arguments to do anything */ - ast_log(LOG_ERROR, "Usage: %s(<varname>,<find-string>[,<replace-string>, <max-replacements>])\n", cmd); + /* Parse the arguments. */ + AST_STANDARD_APP_ARGS(args, data); + + if (args.argc < 2) { + /* Didn't receive enough arguments to do anything */ + ast_log(LOG_ERROR, + "Usage: %s(<varname>,<find-string>[,<replace-string>,[<max-replacements>]])\n", + cmd); return -1; } @@ -892,54 +899,44 @@ static int strreplace(struct ast_channel *chan, const char *cmd, char *data, str return -1; } - /* set varsubstr to the matching variable */ - varsubstr = alloca(strlen(args.varname) + 4); - sprintf(varsubstr, "${%s}", args.varname); - ast_str_substitute_variables(&str, 0, chan, varsubstr); - - p = ast_str_buffer(str); - /* Zero length find strings are a no-no. Kill the function if we run into one. */ if (ast_strlen_zero(args.find_string)) { - ast_log(LOG_ERROR, "The <find-string> must have length > 0\n"); + ast_log(LOG_ERROR, "No <find-string> specified\n"); return -1; } find_size = strlen(args.find_string); - /* If the replace string is a null pointer, set it to an empty string */ - if (!args.replace_string) { - args.replace_string = ""; - } + /* set varsubstr to the matching variable */ + varsubstr = alloca(strlen(args.varname) + 4); + sprintf(varsubstr, "${%s}", args.varname); + ast_str_substitute_variables(&str, 0, chan, varsubstr); - /* - * If max_replacements specified and is a number, max_matches will become that. - * otherwise, just go the length of the input string - */ - if (!(args.max_replacements && (max_matches = atoi(args.max_replacements)))) { - max_matches = strlen(p); + /* Determine how many replacements are allowed. */ + if (!args.max_replacements + || (max_matches = atoi(args.max_replacements)) <= 0) { + /* Unlimited replacements are allowed. */ + max_matches = -1; } - /* Iterate through string finding matches until it is exhausted or we reach max_matches */ - for (x = 0; x < max_matches; x++) { - if ((p = strstr(p, args.find_string))) { - starts[count_len++] = p; - *p = '\0'; - p += find_size; - } else { + /* Generate the search and replaced string. */ + start = ast_str_buffer(str); + for (count = 0; count < max_matches; ++count) { + end = strstr(start, args.find_string); + if (!end) { + /* Did not find a matching substring in the remainder. */ break; } - } - p = ast_str_buffer(str); - - /* here we rebuild the string with the replaced words by using fancy ast_string_append on the buffer */ - for (x = 0; x < count_len; x++) { - ast_str_append(buf, len, "%s", p); - p = starts[x]; - p += find_size; - ast_str_append(buf, len, "%s", args.replace_string); + /* Replace the found substring. */ + *end = '\0'; + ast_str_append(buf, len, "%s", start); + if (args.replace_string) { + /* Append the replacement string */ + ast_str_append(buf, len, "%s", args.replace_string); + } + start = end + find_size; } - ast_str_append(buf, len, "%s", p); + ast_str_append(buf, len, "%s", start); return 0; } -- GitLab