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

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

commit 28a4066fdee2bf91045f4a863e22a08200881ec8
Author: Maxim Smyatkin <[email protected]>
AuthorDate: Sat May 16 21:19:06 2026 +0300

    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.
---
 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 f177516c26f..e458f821a0c 100644
--- a/src/common/stringinfo.c
+++ b/src/common/stringinfo.c
@@ -364,16 +364,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, cuz 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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to