[asterisk-commits] rmudgett: branch 10 r337119 - /branches/10/funcs/func_strings.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 20 17:47:47 CDT 2011


Author: rmudgett
Date: Tue Sep 20 17:47:45 2011
New Revision: 337119

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=337119
Log:
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

Modified:
    branches/10/funcs/func_strings.c

Modified: branches/10/funcs/func_strings.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/funcs/func_strings.c?view=diff&rev=337119&r1=337118&r2=337119
==============================================================================
--- branches/10/funcs/func_strings.c (original)
+++ branches/10/funcs/func_strings.c Tue Sep 20 17:47:45 2011
@@ -859,14 +859,12 @@
 
 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 @@
 		AST_APP_ARG(find_string);
 		AST_APP_ARG(replace_string);
 		AST_APP_ARG(max_replacements);
+		AST_APP_ARG(other);	/* Any remining unused arguments */
 	);
 
+	/* Guarantee output string is empty to start with. */
+	ast_str_reset(*buf);
+
+	if (!str) {
+		/* We failed to allocate str, forget it.  We failed. */
+		return -1;
+	}
+
+	/* Parse the arguments. */
 	AST_STANDARD_APP_ARGS(args, data);
 
-	if (!str) { /* If 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);
+	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;
 	}
 
@@ -891,55 +898,45 @@
 	if (ast_strlen_zero(args.varname)) {
 		return -1;
 	}
+
+	/* 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, "No <find-string> specified\n");
+		return -1;
+	}
+	find_size = strlen(args.find_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);
 
-	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");
-		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 = "";
-	}
-
-	/*
-	 * 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);
-	}
-
-	/* 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 {
+	/* Determine how many replacements are allowed. */
+	if (!args.max_replacements
+		|| (max_matches = atoi(args.max_replacements)) <= 0) {
+		/* Unlimited replacements are allowed. */
+		max_matches = -1;
+	}
+
+	/* 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);
-	}
-	ast_str_append(buf, len, "%s", p);
+
+		/* 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", start);
 
 	return 0;
 }




More information about the asterisk-commits mailing list