regsub converter: empty match advances by 1 byte to avoid loops

This commit is contained in:
2019-02-18 11:08:21 +01:00
parent acf7efcff2
commit 04906a5835
2 changed files with 55 additions and 39 deletions

View File

@ -666,6 +666,13 @@ Otherwise <em>precision</em> is the index (counting from 1) of the match to repl
Without <em>precision</em> (or 0), all matches are replaced. Without <em>precision</em> (or 0), all matches are replaced.
</p> </p>
<p> <p>
When replacing multiple matches, the next match is searched directly after the currently
replaced string, so that the <em>subst</em> string itself will never be modified recursively.
<span class="new">
However if an empty string is matched, searching advances by 1 character in order to
avoid matching the same empty string again.</span>
</p>
<p>
In input this converter pre-processes data received from the device before In input this converter pre-processes data received from the device before
following converters read it. following converters read it.
Converters preceding this one will read unmodified input. Converters preceding this one will read unmodified input.

View File

@ -197,14 +197,15 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
debug("pcre_exec: no match\n"); debug("pcre_exec: no match\n");
break; break;
} }
if (!(fmt.flags & sign_flag) && n < fmt.prec) // without + flag
{
// do not yet replace this match
c += ovector[1];
continue;
}
// replace subexpressions
l = ovector[1] - ovector[0]; l = ovector[1] - ovector[0];
// no prec: replace all matches
// prec with + flag: replace first prec matches
// prec without + flag: replace only match number prec
if ((fmt.flags & sign_flag) || n >= fmt.prec)
{
// replace subexpressions
debug("before [%d]= \"%s\"\n", ovector[0], buffer.expand(start+c,ovector[0])()); debug("before [%d]= \"%s\"\n", ovector[0], buffer.expand(start+c,ovector[0])());
debug("match [%d]= \"%s\"\n", l, buffer.expand(start+c+ovector[0],l)()); debug("match [%d]= \"%s\"\n", l, buffer.expand(start+c+ovector[0],l)());
for (r = 1; r < rc; r++) for (r = 1; r < rc; r++)
@ -243,8 +244,16 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, size_t start
debug("subs = \"%s\"\n", s.expand()()); debug("subs = \"%s\"\n", s.expand()());
} }
buffer.replace(start+c+ovector[0], l, s); buffer.replace(start+c+ovector[0], l, s);
length += s.length() - l; length -= l;
c += ovector[0] + s.length(); length += s.length();
c += s.length();
}
c += ovector[0];
if (l == 0)
{
debug("pcre_exec: empty match\n");
c++; // Empty strings may lead to an endless loop. Match them only once.
}
if (n == fmt.prec) // max match reached if (n == fmt.prec) // max match reached
{ {
debug("pcre_exec: max match %d reached\n", n); debug("pcre_exec: max match %d reached\n", n);