Refuse to rewrite when MaxSubmatch() is too large.
Change-Id: I76f1d92586c3e0f4895ceb16fb019951843497f8
Reviewed-on: https://code-review.googlesource.com/c/re2/+/56870
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/re2.cc b/re2/re2.cc
index 69258af..35fd1cc 100644
--- a/re2/re2.cc
+++ b/re2/re2.cc
@@ -405,6 +405,8 @@
const StringPiece& rewrite) {
StringPiece vec[kVecSize];
int nvec = 1 + MaxSubmatch(rewrite);
+ if (nvec > 1 + re.NumberOfCapturingGroups())
+ return false;
if (nvec > static_cast<int>(arraysize(vec)))
return false;
if (!re.Match(*str, 0, str->size(), UNANCHORED, vec, nvec))
@@ -425,6 +427,8 @@
const StringPiece& rewrite) {
StringPiece vec[kVecSize];
int nvec = 1 + MaxSubmatch(rewrite);
+ if (nvec > 1 + re.NumberOfCapturingGroups())
+ return false;
if (nvec > static_cast<int>(arraysize(vec)))
return false;
@@ -497,9 +501,10 @@
std::string* out) {
StringPiece vec[kVecSize];
int nvec = 1 + MaxSubmatch(rewrite);
+ if (nvec > 1 + re.NumberOfCapturingGroups())
+ return false;
if (nvec > static_cast<int>(arraysize(vec)))
return false;
-
if (!re.Match(text, 0, text.size(), UNANCHORED, vec, nvec))
return false;
@@ -1012,8 +1017,8 @@
int n = (c - '0');
if (n >= veclen) {
if (options_.log_errors()) {
- LOG(ERROR) << "requested group " << n
- << " in regexp " << rewrite.data();
+ LOG(ERROR) << "invalid substitution \\" << n
+ << " from " << veclen << " groups";
}
return false;
}
diff --git a/re2/testing/re2_test.cc b/re2/testing/re2_test.cc
index 52e1f6f..ec457fb 100644
--- a/re2/testing/re2_test.cc
+++ b/re2/testing/re2_test.cc
@@ -224,6 +224,15 @@
ASSERT_EQ(s, "'foo'");
}
+TEST(RE2, MaxSubmatchTooLarge) {
+ std::string s;
+ ASSERT_FALSE(RE2::Extract("foo", "f(o+)", "\\1\\2", &s));
+ s = "foo";
+ ASSERT_FALSE(RE2::Replace(&s, "f(o+)", "\\1\\2"));
+ s = "foo";
+ ASSERT_FALSE(RE2::GlobalReplace(&s, "f(o+)", "\\1\\2"));
+}
+
TEST(RE2, Consume) {
RE2 r("\\s*(\\w+)"); // matches a word, possibly proceeded by whitespace
std::string word;