summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Boeckel <ben.boeckel@kitware.com>2017-07-18 15:08:10 (GMT)
committerBen Boeckel <ben.boeckel@kitware.com>2017-07-21 13:09:56 (GMT)
commitb7941641430feeefadc6f16e2cecf6b50bd9fbe3 (patch)
tree0cd3337f4b799631752d94f3110c6943cd792ecd
parentec049641c46eb788b25713e5d96ff32c89f0e819 (diff)
downloadCMake-b7941641430feeefadc6f16e2cecf6b50bd9fbe3.zip
CMake-b7941641430feeefadc6f16e2cecf6b50bd9fbe3.tar.gz
CMake-b7941641430feeefadc6f16e2cecf6b50bd9fbe3.tar.bz2
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.
-rw-r--r--Source/cmStringCommand.cxx2
-rw-r--r--Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt12
-rw-r--r--Tests/RunCMake/string/RegexMultiMatchClear.cmake20
-rw-r--r--Tests/RunCMake/string/RunCMakeTest.cmake1
4 files changed, 35 insertions, 0 deletions
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 7a097ba..5a6cf48 100644
--- a/Source/cmStringCommand.cxx
+++ b/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();
diff --git a/Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt b/Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt
new file mode 100644
index 0000000..4360d79
--- /dev/null
+++ b/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<--$
diff --git a/Tests/RunCMake/string/RegexMultiMatchClear.cmake b/Tests/RunCMake/string/RegexMultiMatchClear.cmake
new file mode 100644
index 0000000..80b6b3c
--- /dev/null
+++ b/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)")
diff --git a/Tests/RunCMake/string/RunCMakeTest.cmake b/Tests/RunCMake/string/RunCMakeTest.cmake
index 38a77b0..32b61b5 100644
--- a/Tests/RunCMake/string/RunCMakeTest.cmake
+++ b/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)