regex: Match ^ at most once in repeated searches

When doing successive matches, track the input start and current search
start positions separately to prevent the `^` anchor from matching in
the middle of the string.  Add policy CMP0186 to provide compatibility.

Issue: #26629
Fixes: #16899
This commit is contained in:
Nikita Nemkin
2025-01-26 21:55:08 +05:00
parent 90625865e1
commit 5d039f3be3
26 changed files with 301 additions and 28 deletions
+11 -4
View File
@@ -29,6 +29,7 @@
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmStringReplaceHelper.h"
@@ -288,10 +289,16 @@ bool RegexMatchAll(std::vector<std::string> const& args,
// Concatenate all the last arguments together.
std::string input = cmJoin(cmMakeRange(args).advance(4), std::string());
unsigned optAnchor = 0;
if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0186) !=
cmPolicies::NEW) {
optAnchor = cmsys::RegularExpression::BOL_AT_OFFSET;
}
// Scan through the input for all matches.
std::string output;
char const* p = input.c_str();
while (re.find(p)) {
std::string::size_type base = 0;
while (re.find(input, base, optAnchor)) {
status.GetMakefile().ClearMatches();
status.GetMakefile().StoreMatches(re);
std::string::size_type l = re.start();
@@ -305,8 +312,8 @@ bool RegexMatchAll(std::vector<std::string> const& args,
if (!output.empty()) {
output += ";";
}
output += std::string(p + l, r - l);
p += r;
output += re.match();
base = r;
}
// Store the output in the provided variable.