summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-02-03 11:26:31 +0100
committerJo-Philipp Wich <jo@mein.io>2022-02-03 17:04:05 +0100
commit5d0ecd9aefee1be2b51713f7343939b7039a0406 (patch)
treeedcb38ac395e2444dab71b3691317c8e259130ae /lib.c
parent3ad57f116631029263cdbb324a20076006a94d4c (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>
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/lib.c b/lib.c
index ab04b32..7ae9a51 100644
--- a/lib.c
+++ b/lib.c
@@ -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));