From 7ec57f2c50809000653c2ff51cc481f109e6fd7c Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Sun, 20 Sep 2020 10:33:04 +0200 Subject: [PATCH] string: Handle unmatched capturing groups as empty Instead of erroring out. Fixes #7343. --- src/builtin_string.cpp | 7 ++++++- tests/checks/string.fish | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp index 429676f79..330808129 100644 --- a/src/builtin_string.cpp +++ b/src/builtin_string.cpp @@ -1051,8 +1051,13 @@ bool regex_replacer_t::replace_matches(const wcstring &arg) { if (!regex.code) return false; // pcre2_compile() failed if (!replacement) return false; // replacement was an invalid string + // SUBSTITUTE_OVERFLOW_LENGTH causes pcre to return the needed buffer length if the passed one is to small + // SUBSTITUTE_EXTENDED changes how substitution expressions are interpreted (`$` as the special character) + // SUBSTITUTE_UNSET_EMPTY treats unmatched capturing groups as empty instead of erroring. + // SUBSTITUTE_GLOBAL means more than one substitution happens. uint32_t options = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH | PCRE2_SUBSTITUTE_EXTENDED | - (opts.all ? PCRE2_SUBSTITUTE_GLOBAL : 0); + PCRE2_SUBSTITUTE_UNSET_EMPTY | + (opts.all ? PCRE2_SUBSTITUTE_GLOBAL : 0); size_t arglen = arg.length(); PCRE2_SIZE bufsize = (arglen == 0) ? 16 : 2 * arglen; auto output = static_cast(malloc(sizeof(wchar_t) * bufsize)); diff --git a/tests/checks/string.fish b/tests/checks/string.fish index 518388fce..9d5c03acb 100644 --- a/tests/checks/string.fish +++ b/tests/checks/string.fish @@ -619,3 +619,7 @@ echo $status string match -eq asd asd echo $status # CHECK: 0 + +# Unmatched capturing groups are treated as empty +echo 'az' | string replace -r -- 'a(b.+)?z' 'a:$1z' +# CHECK: a:z