Describe the bug
Running regex (|)*a on text a produces a successfully matched submatch[1]. I believe this is incorrect and the correct behavior is to have unmatched submatch[1].
I don't know much about ECMAScript regexes, but from my understanding this is incorrect because * should not allow its subexpression to match empty string. This current behavior of STL differs from the behavior of the regex engine in Chrome and Edge. Also it is inconsistent with similar regex ()*a which correctly doesn't match submatch[1].
Command-line test case
C:\Temp>type repro.cpp
#include <cassert>
#include <iostream>
#include <regex>
#include <string>
void print_submatch(std::ssub_match const& subm, std::string::const_iterator begin)
{
std::cout << "\"" << subm << "\" [";
std::cout << (subm.matched ? "matched" : "not matched");
std::cout << ", start: " << subm.first - begin << ", end: " << subm.second - begin;
std::cout << ']';
}
void run_regex(std::string const& pattern, std::string const& text)
{
std::cout << "Regex: " << pattern << ", Text: \"" << text << "\"" << '\n';
try
{
std::regex re(pattern);
std::smatch match;
std::regex_match(text, match, re);
assert(match.ready());
for (size_t i = 0; i < match.size(); ++i)
{
if (i == 0)
{
std::cout << " Full match: ";
print_submatch(match[i], text.begin());
std::cout << '\n';
}
else
{
std::cout << " Submatch [" << i << "]: ";
print_submatch(match[i], text.begin());
std::cout << '\n';
}
}
}
catch (std::regex_error const& e)
{
std::cout << " Regex error: " << e.what() << '\n';
}
std::cout << '\n';
}
int main()
{
run_regex("()*a", "a");
run_regex("(|)*a", "a");
return 0;
}
C:\Temp>cl /EHsc /W4 /WX .\repro.cpp
Оптимизирующий компилятор Microsoft (R) C/C++ версии 19.44.35219 для x64
(C) Корпорация Майкрософт (Microsoft Corporation). Все права защищены.
repro.cpp
Microsoft (R) Incremental Linker Version 14.44.35219.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:repro.exe
repro.obj
C:\Temp>.\repro.exe
Regex: ()*a, Text: "a"
Full match: "a" [matched, start: 0, end: 1]
Submatch [1]: "" [not matched, start: 1, end: 1]
Regex: (|)*a, Text: "a"
Full match: "a" [matched, start: 0, end: 1]
Submatch [1]: "" [matched, start: 0, end: 0]
Expected behavior
The expected behavior is to have output
Regex: (|)*a, Text: "a"
Full match: "a" [matched, start: 0, end: 1]
Submatch [1]: "" [not matched, start: 1, end: 1]
similar to the other test case and the behavior of the browsers.
I also made a small sample for browsers. I used it to validate that the behavior of std::regex doesn't match theirs:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JS Regex Repro</title>
</head>
<body>
<pre id="output"></pre>
<script>
const output = document.getElementById('output');
function log(msg) {
output.textContent += msg + '\n';
}
function runRegex(patternStr, text) {
log(`Regex: /${patternStr}/, Text: "${text}"`);
try {
const re = new RegExp(patternStr, 'd');
const match = re.exec(text);
if (match) {
for (let i = 0; i < match.length; i++) {
const prefix = i === 0 ? " Full match: " : ` Submatch [${i}]: `;
const value = match[i] === undefined ? "undefined" : `"${match[i]}"`;
const matched = match[i] !== undefined ? "matched" : "not matched";
const start = match.indices[i] === undefined ? "undefined" : match.indices[i][0];
const end = match.indices[i] === undefined ? "undefined" : match.indices[i][1];
log(`${prefix}${value} [${matched}, start: ${start}, end: ${end}]`);
}
} else {
log(` No match.`);
}
} catch (e) {
log(` Error: ${e.message}`);
}
log('');
}
runRegex('()*a', 'a');
runRegex('(|)*a', 'a');
</script>
</body>
</html>
STL version
_MSVC_STL_UPDATE value is 202503.
Describe the bug
Running regex
(|)*aon textaproduces a successfully matchedsubmatch[1]. I believe this is incorrect and the correct behavior is to have unmatchedsubmatch[1].I don't know much about ECMAScript regexes, but from my understanding this is incorrect because
*should not allow its subexpression to match empty string. This current behavior of STL differs from the behavior of the regex engine in Chrome and Edge. Also it is inconsistent with similar regex()*awhich correctly doesn't matchsubmatch[1].Command-line test case
Expected behavior
The expected behavior is to have output
similar to the other test case and the behavior of the browsers.
I also made a small sample for browsers. I used it to validate that the behavior of std::regex doesn't match theirs:
STL version
_MSVC_STL_UPDATEvalue is202503.