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); } }