summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2019-06-20 15:40:15 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2019-06-20 15:40:15 +0000
commit899626be22606a46f6adcd3ecb19de4060f70803 (patch)
treed8a8885c2c6475a2fe53c791436e4052a53976c7
parentf84cd4edbba57ed0faffbbd79d7b140b742ea297 (diff)
Fix how regex substitution works with empty matches.
-rw-r--r--usr.bin/tmux/regsub.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/usr.bin/tmux/regsub.c b/usr.bin/tmux/regsub.c
index a7e14505346..cf5b917aee3 100644
--- a/usr.bin/tmux/regsub.c
+++ b/usr.bin/tmux/regsub.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: regsub.c,v 1.1 2019/06/13 19:46:00 nicm Exp $ */
+/* $OpenBSD: regsub.c,v 1.2 2019/06/20 15:40:14 nicm Exp $ */
/*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -63,7 +63,8 @@ regsub(const char *pattern, const char *with, const char *text, int flags)
{
regex_t r;
regmatch_t m[10];
- size_t start, end, len = 0;
+ ssize_t start, end, last, len = 0;
+ int empty = 0;
char *buf = NULL;
if (*text == '\0')
@@ -72,9 +73,10 @@ regsub(const char *pattern, const char *with, const char *text, int flags)
return (NULL);
start = 0;
+ last = 0;
end = strlen(text);
- while (start != end) {
+ while (start <= end) {
m[0].rm_so = start;
m[0].rm_eo = end;
@@ -82,14 +84,29 @@ regsub(const char *pattern, const char *with, const char *text, int flags)
regsub_copy(&buf, &len, text, start, end);
break;
}
- if (m[0].rm_so == m[0].rm_eo) {
- regsub_copy(&buf, &len, text, start, end);
- break;
- }
- regsub_copy(&buf, &len, text, start, m[0].rm_so);
- regsub_expand(&buf, &len, with, text, m, nitems(m));
- start = m[0].rm_eo;
+ /*
+ * Append any text not part of this match (from the end of the
+ * last match).
+ */
+ regsub_copy(&buf, &len, text, last, m[0].rm_so);
+
+ /*
+ * If the last match was empty and this one isn't (it is either
+ * later or has matched text), expand this match. If it is
+ * empty, move on one character and try again from there.
+ */
+ if (empty || m[0].rm_so != last || m[0].rm_so != m[0].rm_eo) {
+ regsub_expand(&buf, &len, with, text, m, nitems(m));
+
+ last = m[0].rm_eo;
+ start = m[0].rm_eo;
+ empty = 0;
+ } else {
+ last = m[0].rm_eo;
+ start = m[0].rm_eo + 1;
+ empty = 1;
+ }
}
buf[len] = '\0';