@b4n approved this pull request.
I extracted the old and new code an tested a bit, and that also works great. FWIW, if somebody didn't catch what the issue was (as in fact it's not mentioned anywhere but "infinite loop"): if the replacement contains the search term, it'll be replaced recursively forever (infinite loop + steady memory growth).
<details> <summary>FWIW, I tested using this program:</summary>
```c #include <stdlib.h> #include <stdio.h> #include <string.h> #include <glib.h>
#if 0 /* old */ static void replace_all(GString *haystack, const gchar *needle, const gchar *replacement) { gchar *ptr; gsize needle_len = strlen(needle);
/* For each occurrence of needle in haystack */ while ((ptr = strstr(haystack->str, needle)) != NULL) { goffset offset = ptr - haystack->str; g_string_erase(haystack, offset, needle_len); g_string_insert(haystack, offset, replacement); } } #else /* new */ static void replace_all(GString *haystack, const gchar *needle, const gchar *replacement) { gchar *ptr; gsize needle_len = strlen(needle); gsize replacement_len = strlen(replacement); goffset offset = 0;
/* For each occurrence of needle in haystack */ while ((ptr = strstr(haystack->str + offset, needle)) != NULL) { offset = ptr - haystack->str; g_string_erase(haystack, offset, needle_len); g_string_insert(haystack, offset, replacement); offset += replacement_len; } } #endif
int main(void) { #define TEST_REPLACE_ALL(hs, s, r, ex) \ G_STMT_START { \ GString *haystack_ = g_string_new(hs); \ replace_all(haystack_, s, r); \ g_assert_cmpstr(haystack_->str, ==, ex); \ g_string_free(haystack_, TRUE); \ } G_STMT_END
TEST_REPLACE_ALL("hello", "a", "b", "hello"); TEST_REPLACE_ALL("hallo", "a", "b", "hbllo"); TEST_REPLACE_ALL("foobarbaz", "ba", "BA", "fooBArBAz"); TEST_REPLACE_ALL("ababab", "ba", "BA", "aBABAb"); TEST_REPLACE_ALL("ababab", "ab", "AB", "ABABAB"); TEST_REPLACE_ALL("foobarbaz", "o", "oo", "foooobarbaz");
#undef TEST_REPLACE_ALL
return 0; } ```