diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-02-03 11:26:31 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-02-03 17:04:05 +0100 |
commit | 5d0ecd9aefee1be2b51713f7343939b7039a0406 (patch) | |
tree | edcb38ac395e2444dab71b3691317c8e259130ae | |
parent | 3ad57f116631029263cdbb324a20076006a94d4c (diff) |
lib: fix infinite loop on empty regexp matches in uc_replace()
The regular expression `/()/` will match the empty string, causing the
match loop to never advance. Add extra logic to deal with this case,
similar to the empty separator string logic.
Apply a similar exception to replacements of empty search strings, those
should yield the same result as empty regexp matches.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | lib.c | 25 |
1 files changed, 20 insertions, 5 deletions
@@ -1975,7 +1975,12 @@ uc_replace(uc_vm_t *vm, size_t nargs) uc_replace_str(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), resbuf); } - p += pmatch[0].rm_eo; + if (pmatch[0].rm_so != pmatch[0].rm_eo) + p += pmatch[0].rm_eo; + else if (*p) + ucv_stringbuf_addstr(resbuf, p++, 1); + else + break; if (re->global) eflags |= REG_NOTBOL; @@ -1989,8 +1994,10 @@ uc_replace(uc_vm_t *vm, size_t nargs) pt = uc_cast_string(vm, &pattern, &pt_freeable); pl = strlen(pt); - for (l = p = sb; *p; p++) { - if (!strncmp(p, pt, pl)) { + l = p = sb; + + while (true) { + if (pl == 0 || !strncmp(p, pt, pl)) { ucv_stringbuf_addstr(resbuf, l, p - l); pmatch[0].rm_so = p - l; @@ -2013,9 +2020,17 @@ uc_replace(uc_vm_t *vm, size_t nargs) uc_replace_str(vm, replace, l, pmatch, 1, resbuf); } - l = p + pl; - p += pl - 1; + if (pl) { + l = p + pl; + p += pl - 1; + } + else { + l = p; + } } + + if (!*p++) + break; } ucv_stringbuf_addstr(resbuf, l, strlen(l)); |