Fix infinite loops in replaceStringInfoString

The function had a few problems:
- replace ="a" and replacement="ab" would give an infinite loop leading
  to OOM. We have a similar case in pg_dump: replace="range",
  replacement="multirange"
- Copying the whole string each time there is a match
- Empty replace pattern also leads to infinite loop

We can still do better: for example count number of matches and do a
single allocation, or even run the replacement inplace. But it's
probably not worth it.
diff --git a/src/common/stringinfo.c b/src/common/stringinfo.c
index f177516..e458f82 100644
--- a/src/common/stringinfo.c
+++ b/src/common/stringinfo.c
@@ -364,16 +364,32 @@
 void
 replaceStringInfoString(StringInfo str, char *replace, char *replacement)
 {
-	char	*ptr;
+	char	*match_ptr = NULL;
+	char	*start_ptr = str->data;
+	char	*dup = NULL;
+	size_t	replace_len = strlen(replace);
 
-	while ((ptr = strstr(str->data, replace)) != NULL)
+	// prevent empty loop, cuz strstr will always return start_ptr
+	if (replace_len == 0)
+		return;
+
+	while ((match_ptr = strstr(start_ptr, replace)) != NULL)
 	{
-		char	   *dup = pstrdup(str->data);
+		if (dup == NULL)
+		{
+			dup = pstrdup(str->data);
+			start_ptr = dup;
+			match_ptr = dup + (match_ptr - str->data);
+			resetStringInfo(str);
+		}
 
-		resetStringInfo(str);
-		appendBinaryStringInfo(str, dup, ptr - str->data);
+		appendBinaryStringInfo(str, start_ptr, match_ptr - start_ptr);
 		appendStringInfoString(str, replacement);
-		appendStringInfoString(str, dup + (ptr - str->data) + strlen(replace));		
+		start_ptr = match_ptr + replace_len;
+	}
+	if (dup != NULL)
+	{
+		appendStringInfoString(str, start_ptr);
 		pfree(dup);
 	}
 }