Commit 6ffc4323 authored by Brad King's avatar Brad King

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.
parent 656768cf
......@@ -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;
......
foreach(n 0 1 2 3 4 5 6 7 8 9 COUNT)
if(CMAKE_MATCH_${n} MATCHES "x")
endif()
endforeach()
......@@ -5,5 +5,7 @@ run_cmake(IsDirectory)
run_cmake(IsDirectoryLong)
run_cmake(elseif-message)
run_cmake(MatchesSelf)
run_cmake(TestNameThatExists)
run_cmake(TestNameThatDoesNotExist)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment