summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-02-01 09:49:08 -0500
committerBrad King <brad.king@kitware.com>2016-02-01 10:05:10 -0500
commit6ffc4323670f3671f262b3e9f035f1ea3f714986 (patch)
tree4058de83fa61e55afe5b841534f4b268a97a758e
parent656768cffe981e02f12fe51d6723d21176a46329 (diff)
downloadcmake-6ffc4323670f3671f262b3e9f035f1ea3f714986.tar.gz
cmConditionEvaluator: Fix matching of `CMAKE_MATCH_*` values (#15944)
While evaluating `if(MATCHES)` we get a `const char*` pointer to the string to be matched. On code like if(CMAKE_MATCH_COUNT MATCHES "Y") the string to be matched may be owned by our own result variables. We must move the value to our own buffer before clearing them. Otherwise we risk reading freed storage.
-rw-r--r--Source/cmConditionEvaluator.cxx10
-rw-r--r--Tests/RunCMake/if/MatchesSelf.cmake4
-rw-r--r--Tests/RunCMake/if/RunCMakeTest.cmake2
3 files changed, 16 insertions, 0 deletions
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 5330acdaf8..6a0ebec2d2 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -12,6 +12,7 @@
#include "cmConditionEvaluator.h"
#include "cmOutputConverter.h"
+#include "cmAlgorithms.h"
cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
const cmListFileContext &context,
@@ -578,6 +579,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList &newArgs,
cmake::MessageType &status)
{
int reducible;
+ std::string def_buf;
const char *def;
const char *def2;
do
@@ -594,6 +596,14 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList &newArgs,
IsKeyword("MATCHES", *argP1))
{
def = this->GetVariableOrString(*arg);
+ if (def != arg->c_str() // yes, we compare the pointer value
+ && cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_"))
+ {
+ // The string to match is owned by our match result variables.
+ // Move it to our own buffer before clearing them.
+ def_buf = def;
+ def = def_buf.c_str();
+ }
const char* rex = argP2->c_str();
this->Makefile.ClearMatches();
cmsys::RegularExpression regEntry;
diff --git a/Tests/RunCMake/if/MatchesSelf.cmake b/Tests/RunCMake/if/MatchesSelf.cmake
new file mode 100644
index 0000000000..3131ac4f48
--- /dev/null
+++ b/Tests/RunCMake/if/MatchesSelf.cmake
@@ -0,0 +1,4 @@
+foreach(n 0 1 2 3 4 5 6 7 8 9 COUNT)
+ if(CMAKE_MATCH_${n} MATCHES "x")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake
index 3f4d2a24d0..077d00a058 100644
--- a/Tests/RunCMake/if/RunCMakeTest.cmake
+++ b/Tests/RunCMake/if/RunCMakeTest.cmake
@@ -5,5 +5,7 @@ run_cmake(IsDirectory)
run_cmake(IsDirectoryLong)
run_cmake(elseif-message)
+run_cmake(MatchesSelf)
+
run_cmake(TestNameThatExists)
run_cmake(TestNameThatDoesNotExist)