You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudberry.apache.org by dj...@apache.org on 2026/07/14 05:37:05 UTC

(cloudberry) branch main updated: Fix infinite loop in replaceStringInfoString (#1750)

This is an automated email from the ASF dual-hosted git repository.

tuhaihe pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git


The following commit(s) were added to refs/heads/main by this push:
     new 7f5c3620ce6 Fix infinite loop in replaceStringInfoString (#1750)
7f5c3620ce6 is described below

commit 7f5c3620ce6499713875b5ea9a259da173dd9e64
Author: Smyatkin Maxim <sm...@gmail.com>
AuthorDate: Tue Jul 14 08:37:01 2026 +0300

    Fix infinite loop in replaceStringInfoString (#1750)
    
    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.
---
 src/common/stringinfo.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/common/stringinfo.c b/src/common/stringinfo.c
index 0dbca75f248..52d1e30526c 100644
--- a/src/common/stringinfo.c
+++ b/src/common/stringinfo.c
@@ -361,16 +361,32 @@ enlargeStringInfo(StringInfo str, int needed)
 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)
-	{
-		char	   *dup = pstrdup(str->data);
+	// prevent empty loop, because strstr will always return start_ptr
+	if (replace_len == 0)
+		return;
 
-		resetStringInfo(str);
-		appendBinaryStringInfo(str, dup, ptr - str->data);
+	while ((match_ptr = strstr(start_ptr, replace)) != NULL)
+	{
+		if (dup == NULL)
+		{
+			dup = pstrdup(str->data);
+			start_ptr = dup;
+			match_ptr = dup + (match_ptr - str->data);
+			resetStringInfo(str);
+		}
+
+		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);
 	}
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cloudberry.apache.org
For additional commands, e-mail: commits-help@cloudberry.apache.org