From 9f5b5bf5d44e7741a4ca28cc2b67e479b088c9b2 Mon Sep 17 00:00:00 2001 From: TreeHunter <60896014+TreeHunter9@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:06:33 +0300 Subject: [PATCH] Fix regular expression value substitition in fbtrace.conf after macro substitition Co-authored-by: Artyom Ivanov --- src/common/config/config_file.cpp | 55 +++++++++++++++++---- src/common/config/config_file.h | 3 ++ src/utilities/ntrace/TraceConfiguration.cpp | 5 +- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/common/config/config_file.cpp b/src/common/config/config_file.cpp index 022f83c667..0bb0df21c7 100644 --- a/src/common/config/config_file.cpp +++ b/src/common/config/config_file.cpp @@ -414,6 +414,41 @@ ConfigFile::LineType ConfigFile::parseLine(const char* fileName, const String& i * Substitute macro values in a string */ +unsigned ConfigFile::getDirSeparatorLength(const String& value, size_t separatorPosition) const +{ + if (separatorPosition >= value.length()) + return 0; + + const char symbol = value[separatorPosition]; + if (symbol == '/') + return 1; + + if (flags & REGEXP_SUPPORT && symbol == '\\') + { + // Check forward and backward for second backslash + if (separatorPosition + 1 < value.length() && value[separatorPosition + 1] == '\\') + return 2; + if (separatorPosition > 0 && value[separatorPosition - 1] == '\\') + return 2; + } + else if (symbol == '\\') + return 1; + + return 0; +} + +void ConfigFile::adjustMacroReplacePositions(const String& value, const String& macro, String::size_type& from, String::size_type& to) const +{ + if (macro.empty()) + return; + + // Remove dir separators from value string if macro already contains them at start or end + if (macro[0] == PathUtils::dir_sep && from > 0) + from -= getDirSeparatorLength(value, from - 1); + if (macro[macro.length() - 1] == PathUtils::dir_sep) + to += getDirSeparatorLength(value, to); +} + bool ConfigFile::macroParse(String& value, const char* fileName) const { String::size_type pos = 0; @@ -442,19 +477,21 @@ bool ConfigFile::macroParse(String& value, const char* fileName) const } // Avoid incorrect slashes in pathnames - PathUtils::fixupSeparators(value.begin()); PathUtils::fixupSeparators(macro.begin()); - if (subFrom > 0 && value[subFrom - 1] == PathUtils::dir_sep && - macro.length() > 0 && macro[0] == PathUtils::dir_sep) + if (flags & REGEXP_SUPPORT) { - --subFrom; - } - if (subTo < value.length() && value[subTo] == PathUtils::dir_sep && - macro.length() > 0 && macro[macro.length() - 1] == PathUtils::dir_sep) - { - ++subTo; + size_t pos = 0; + while ((pos = macro.find('\\', pos)) != String::npos) + { + macro.insert(pos, "\\"); + pos += 2; + } } + else + PathUtils::fixupSeparators(value.begin()); + + adjustMacroReplacePositions(value, macro, subFrom, subTo); // Now perform operation value.replace(subFrom, subTo - subFrom, macro); diff --git a/src/common/config/config_file.h b/src/common/config/config_file.h index f48cc52bf4..50473e0918 100644 --- a/src/common/config/config_file.h +++ b/src/common/config/config_file.h @@ -57,6 +57,7 @@ public: static const USHORT NATIVE_ORDER = 0x04; static const USHORT NO_COMMENTS = 0x08; static const USHORT CUSTOM_MACROS = 0x10; + static const USHORT REGEXP_SUPPORT = 0x20; // enum to distinguish ctors enum UseText {USE_TEXT}; @@ -144,6 +145,8 @@ private: void include(const char* currentFileName, const Firebird::PathName& path); bool wildCards(const char* currentFileName, const Firebird::PathName& pathPrefix, FilesArray& components); bool substituteStandardDir(const String& from, String& to) const; + void adjustMacroReplacePositions(const String& value, const String& macro, String::size_type& from, String::size_type& to) const; + unsigned getDirSeparatorLength(const String& value, size_t subFrom) const; }; #endif // CONFIG_CONFIG_FILE_H diff --git a/src/utilities/ntrace/TraceConfiguration.cpp b/src/utilities/ntrace/TraceConfiguration.cpp index e3cd9dac97..fb5518515d 100644 --- a/src/utilities/ntrace/TraceConfiguration.cpp +++ b/src/utilities/ntrace/TraceConfiguration.cpp @@ -29,6 +29,7 @@ #include "../../common/SimilarToRegex.h" #include "../../common/isc_f_proto.h" #include "../../common/db_alias.h" +#include "../../common/os/path_utils.h" using namespace Firebird; @@ -46,6 +47,7 @@ void TraceCfgReader::readTraceConfiguration(const char* text, if (!found && el->name == #NAME) { \ Firebird::PathName temp; \ expandPattern(el, temp); \ + PathUtils::fixupSeparators(temp.begin()); \ m_config.NAME = temp.c_str(); \ found = true; \ } @@ -70,7 +72,8 @@ void TraceCfgReader::readTraceConfiguration(const char* text, void TraceCfgReader::readConfig() { - ConfigFile cfgFile(ConfigFile::USE_TEXT, m_text, ConfigFile::HAS_SUB_CONF | ConfigFile::NATIVE_ORDER); + ConfigFile cfgFile(ConfigFile::USE_TEXT, m_text, ConfigFile::HAS_SUB_CONF | ConfigFile::NATIVE_ORDER + | ConfigFile::REGEXP_SUPPORT); m_subpatterns[0].start = 0; m_subpatterns[0].end = m_databaseName.length();