Przeglądaj źródła

cmStringCommand: clear intermediate matches

When `string(REGEX REPLACE)` or `string(REGEX MATCHALL)` loop
internally, they store their matches, but they do not clear the previous
match from an earlier iteration. This can leave the contents of
`CMAKE_MATCH_<N>` with bogus values for later matches in the string if
they have groups which earlier matched a non-empty string, but now match
an empty string.

Fixes #17079.
Ben Boeckel 8 lat temu
rodzic
commit
b794164143

+ 2 - 0
Source/cmStringCommand.cxx

@@ -309,6 +309,7 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
   std::string output;
   const char* p = input.c_str();
   while (re.find(p)) {
+    this->Makefile->ClearMatches();
     this->Makefile->StoreMatches(re);
     std::string::size_type l = re.start();
     std::string::size_type r = re.end();
@@ -391,6 +392,7 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
   std::string output;
   std::string::size_type base = 0;
   while (re.find(input.c_str() + base)) {
+    this->Makefile->ClearMatches();
     this->Makefile->StoreMatches(re);
     std::string::size_type l2 = re.start();
     std::string::size_type r = re.end();

+ 12 - 0
Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt

@@ -0,0 +1,12 @@
+^matches: Some::;Scope
+results from: string\(REGEX MATCHALL\)
+CMAKE_MATCH_0: -->Scope<--
+CMAKE_MATCH_1: -->Scope<--
+CMAKE_MATCH_2: --><--
+CMAKE_MATCH_COUNT: -->1<--
+replace: \[Some\]\[Scope\]
+results from: string\(REGEX REPLACE\)
+CMAKE_MATCH_0: -->Scope<--
+CMAKE_MATCH_1: -->Scope<--
+CMAKE_MATCH_2: --><--
+CMAKE_MATCH_COUNT: -->1<--$

+ 20 - 0
Tests/RunCMake/string/RegexMultiMatchClear.cmake

@@ -0,0 +1,20 @@
+cmake_minimum_required (VERSION 3.0)
+project (RegexClear NONE)
+
+function (output_results msg)
+  message("results from: ${msg}")
+  message("CMAKE_MATCH_0: -->${CMAKE_MATCH_0}<--")
+  message("CMAKE_MATCH_1: -->${CMAKE_MATCH_1}<--")
+  message("CMAKE_MATCH_2: -->${CMAKE_MATCH_2}<--")
+  message("CMAKE_MATCH_COUNT: -->${CMAKE_MATCH_COUNT}<--")
+endfunction ()
+
+set(haystack "Some::Scope")
+
+string(REGEX MATCHALL "^([^:]+)(::)?" matches "${haystack}")
+message("matches: ${matches}")
+output_results("string(REGEX MATCHALL)")
+
+string(REGEX REPLACE "^([^:]+)(::)?" "[\\1]" replace "${haystack}")
+message("replace: ${replace}")
+output_results("string(REGEX REPLACE)")

+ 1 - 0
Tests/RunCMake/string/RunCMakeTest.cmake

@@ -20,6 +20,7 @@ run_cmake(UuidMissingTypeValue)
 run_cmake(UuidBadType)
 
 run_cmake(RegexClear)
+run_cmake(RegexMultiMatchClear)
 
 run_cmake(UTF-16BE)
 run_cmake(UTF-16LE)