diff --git a/include/maxscale/pcre2.hh b/include/maxscale/pcre2.hh index 37f42e5d9..15fa148d1 100644 --- a/include/maxscale/pcre2.hh +++ b/include/maxscale/pcre2.hh @@ -28,10 +28,15 @@ namespace maxscale * @param re Compiled pattern to use * @param subject Subject string * @param replace Replacement string + * @param error Pointer to std::string where any error messages are stored * - * @return The replaced string or the original string if no replacement was made + * @return The replaced string or the original string if no replacement was made. Returns an empty string when + * any PCRE2 error is encountered. */ -std::string pcre2_substitute(pcre2_code* re, const std::string& subject, const std::string& replace); +std::string pcre2_substitute(pcre2_code* re, + const std::string& subject, + const std::string& replace, + std::string* error = nullptr); /** * @class CloserTraits pcre2.hh diff --git a/server/core/maxscale_pcre2.cc b/server/core/maxscale_pcre2.cc index 67030942e..db6599b9e 100644 --- a/server/core/maxscale_pcre2.cc +++ b/server/core/maxscale_pcre2.cc @@ -248,8 +248,12 @@ bool mxs_pcre2_check_match_exclude(pcre2_code* re_match, namespace maxscale { -std::string pcre2_substitute(pcre2_code* re, const std::string& subject, const std::string& replace) +std::string pcre2_substitute(pcre2_code* re, + const std::string& subject, + const std::string& replace, + std::string* error) { + mxb_assert(re); std::string rval = subject; size_t size_tmp = rval.size(); int rc; @@ -263,7 +267,21 @@ std::string pcre2_substitute(pcre2_code* re, const std::string& subject, const s size_tmp = rval.size(); } - rval.resize(size_tmp); + if (rc < 0) + { + if (error) + { + char errbuf[1024]; + pcre2_get_error_message(rc, (PCRE2_UCHAR*)errbuf, sizeof(errbuf)); + *error = errbuf; + } + + rval.clear(); + } + else + { + rval.resize(size_tmp); + } return rval; } diff --git a/server/modules/filter/binlogfilter/binlogfilter.hh b/server/modules/filter/binlogfilter/binlogfilter.hh index 2f1ed2feb..1b5305be0 100644 --- a/server/modules/filter/binlogfilter/binlogfilter.hh +++ b/server/modules/filter/binlogfilter/binlogfilter.hh @@ -30,6 +30,7 @@ struct BinlogConfig , exclude(pParams->get_compiled_regex("exclude", 0, nullptr).release()) , md_exclude(exclude ? pcre2_match_data_create_from_pattern(exclude, nullptr) : nullptr) , rewrite_src(pParams->get_compiled_regex(REWRITE_SRC, 0, nullptr).release()) + , rewrite_src_pattern(pParams->get_string(REWRITE_SRC)) , rewrite_dest(pParams->get_string(REWRITE_DEST)) { } @@ -39,6 +40,7 @@ struct BinlogConfig pcre2_code* exclude; pcre2_match_data* md_exclude; pcre2_code* rewrite_src; + std::string rewrite_src_pattern; std::string rewrite_dest; }; diff --git a/server/modules/filter/binlogfilter/binlogfiltersession.cc b/server/modules/filter/binlogfilter/binlogfiltersession.cc index 166ab5ccc..ee7d2df50 100644 --- a/server/modules/filter/binlogfilter/binlogfiltersession.cc +++ b/server/modules/filter/binlogfilter/binlogfiltersession.cc @@ -851,10 +851,17 @@ void BinlogFilterSession::checkStatement(GWBUF** buffer, const REP_HEADER& hdr) if (!m_skip && config.rewrite_src) { - auto new_db = mxs::pcre2_substitute(config.rewrite_src, db, config.rewrite_dest); - auto new_sql = mxs::pcre2_substitute(config.rewrite_src, sql, config.rewrite_dest); + std::string err; + auto new_db = mxs::pcre2_substitute(config.rewrite_src, db, config.rewrite_dest, &err); + auto new_sql = mxs::pcre2_substitute(config.rewrite_src, sql, config.rewrite_dest, &err); - if (db != new_db || sql != new_sql) + if (new_db.empty() || new_sql.empty()) + { + MXS_ERROR("PCRE2 error on pattern '%s' with replacement '%s': %s", + config.rewrite_src_pattern.c_str(), + config.rewrite_dest.c_str(), err.c_str()); + } + else if (db != new_db || sql != new_sql) { db = new_db; sql = new_sql;