From f721a2592bea2d35aee0594b4d939ca9210d4437 Mon Sep 17 00:00:00 2001
From: Ken Rice <krice@freeswitch.org>
Date: Mon, 1 Jul 2013 17:03:00 -0500
Subject: [PATCH] --resolve FS-5566

When you use $12345 in regex substitutions, it isn't obvious
whenever you mean $1-concatenated-2345 or $12-concatenated-345
or any other variation.  In all other languages, in order to
solve this ambiguity, a braces {} are allowed to be used to
separate variable name (or a reference) from surrounding text,
like ${1}2345 or ${12}345.  Use the same for freeswitch too.

While at it, fix a buffer overflow as well: the index[] variable
which is used to copy the "variable" name is 10 chars long, but
it is used in the code without bounds checking, so a reference
which is >9 chars long ($1234567890) will overflow the buffer,
crashing freeswitch.

And another overflow is in the way how size of the "substituted"
variable is handled.  First, in the outer loop, we compare the
wrong variable with the size of `substituted' buffer (amount of
bytes we took from the source instead of amount of bytes we
used in `substituted').  And second, when actual regex match
is being substitured, amount of room in `substituted' variable
is not checked at all.

Patch contributed by Michael Tokarev <mjt@tls.msk.ru>
---
 src/switch_regex.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/switch_regex.c b/src/switch_regex.c
index 0a3479582e..2a98638134 100644
--- a/src/switch_regex.c
+++ b/src/switch_regex.c
@@ -132,20 +132,37 @@ SWITCH_DECLARE(void) switch_perform_substitution(switch_regex_t *re, int match_c
 	const char *replace = NULL;
 	switch_size_t x, y = 0, z = 0;
 	int num = 0;
+	int brace;
 
-	for (x = 0; x < (len - 1) && x < strlen(data);) {
+	for (x = 0; y < (len - 1) && x < strlen(data);) {
 		if (data[x] == '$') {
 			x++;
 
+			brace = data[x] == '{';
+			if (brace) {
+				x++;
+			}
+
 			if (!(data[x] > 47 && data[x] < 58)) {
+				x -= brace;
 				substituted[y++] = data[x - 1];
 				continue;
 			}
 
-			while (data[x] > 47 && data[x] < 58) {
+			while (data[x] > 47 && data[x] < 58 && z < sizeof(index) - 1) {
 				index[z++] = data[x];
 				x++;
 			}
+			if (brace) {
+				if (data[x] != '}') {
+					x -= z - 1;
+					substituted[y++] = data[x - 1];
+					continue;
+				}
+				else {
+					x++;
+				}
+			}
 			index[z++] = '\0';
 			z = 0;
 			num = atoi(index);
@@ -156,7 +173,7 @@ SWITCH_DECLARE(void) switch_perform_substitution(switch_regex_t *re, int match_c
 
 			if (pcre_get_substring(field_data, ovector, match_count, num, &replace) > 0) {
 				switch_size_t r;
-				for (r = 0; r < strlen(replace); r++) {
+				for (r = 0; r < strlen(replace) && y < (len - 1); r++) {
 					substituted[y++] = replace[r];
 				}
 				pcre_free_substring(replace);